Vendor drop Added: vendor/wine/dlls/advapi32/ Added: vendor/wine/dlls/advapi32/crypt.c Added: vendor/wine/dlls/advapi32/crypt_des.c Added: vendor/wine/dlls/advapi32/crypt_lmhash.c Added: vendor/wine/dlls/advapi32/crypt_md4.c Added: vendor/wine/dlls/advapi32/crypt_md5.c Added: vendor/wine/dlls/advapi32/crypt_sha.c _____
Added: vendor/wine/dlls/advapi32/crypt.c --- vendor/wine/dlls/advapi32/crypt.c 2005-02-20 11:11:20 UTC (rev 13675) +++ vendor/wine/dlls/advapi32/crypt.c 2005-02-20 11:19:28 UTC (rev 13676) @@ -0,0 +1,1954 @@
+/* + * Copyright 1999 Ian Schmidt + * Copyright 2001 Travis Michielsen + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/********************************************************************** * + * + * TODO: + * - Reference counting + * - Thread-safing + * - Signature checking + */ + +#include <time.h> +#include <stdlib.h> +#include <stdio.h> + +#include "crypt.h" +#include "winnls.h" +#include "winreg.h" +#include "wine/debug.h" +#include "winternl.h" +#include "ntstatus.h" + +WINE_DEFAULT_DEBUG_CHANNEL(crypt); + +HWND crypt_hWindow = 0; + +#define CRYPT_ReturnLastError(err) {SetLastError(err); return FALSE;} + +#define CRYPT_Alloc(size) ((LPVOID)LocalAlloc(LMEM_ZEROINIT, size)) +#define CRYPT_Free(buffer) (LocalFree((HLOCAL)buffer)) + +static inline PSTR CRYPT_GetProvKeyName(PCSTR pProvName) +{ + PCSTR KEYSTR = "Software\Microsoft\Cryptography\Defaults\Provider\"; + PSTR keyname; + + keyname = CRYPT_Alloc(strlen(KEYSTR) + strlen(pProvName) +1); + if (keyname) + { + strcpy(keyname, KEYSTR); + strcpy(keyname + strlen(KEYSTR), pProvName); + } else + SetLastError(ERROR_NOT_ENOUGH_MEMORY); + return keyname; +} + +static inline PSTR CRYPT_GetTypeKeyName(DWORD dwType, BOOL user) +{ + PCSTR MACHINESTR = "Software\Microsoft\Cryptography\Defaults\Provider Types\Type XXX"; + PCSTR USERSTR = "Software\Microsoft\Cryptography\Provider Type XXX"; + PSTR keyname; + PSTR ptr; + + keyname = CRYPT_Alloc( (user ? strlen(USERSTR) : strlen(MACHINESTR)) +1); + if (keyname) + { + user ? strcpy(keyname, USERSTR) : strcpy(keyname, MACHINESTR); + ptr = keyname + strlen(keyname); + *(--ptr) = (dwType % 10) + '0'; + *(--ptr) = ((dwType / 10) % 10) + '0'; + *(--ptr) = (dwType / 100) + '0'; + } else + SetLastError(ERROR_NOT_ENOUGH_MEMORY); + return keyname; +} + +/* CRYPT_UnicodeTOANSI + * wstr - unicode string + * str - pointer to ANSI string + * strsize - size of buffer pointed to by str or -1 if we have to do the allocation + * + * returns TRUE if unsuccessfull, FALSE otherwise. + * if wstr is NULL, returns TRUE and sets str to NULL! Value of str should be checked after call + */ +static inline BOOL CRYPT_UnicodeToANSI(LPCWSTR wstr, LPSTR* str, int strsize) +{ + int count; + + if (!wstr) + { + *str = NULL; + return TRUE; + } + count = WideCharToMultiByte(CP_ACP, 0, wstr, -1, NULL, 0, NULL, NULL); + if (strsize == -1) + *str = CRYPT_Alloc(count * sizeof(CHAR)); + else + count = min( count, strsize ); + if (*str) + { + WideCharToMultiByte(CP_ACP, 0, wstr, -1, *str, count, NULL, NULL); + return TRUE; + } + SetLastError(ERROR_NOT_ENOUGH_MEMORY); + return FALSE; +} + +/* CRYPT_ANSITOUnicode + * str - ANSI string + * wstr - pointer to unicode string + * wstrsize - size of buffer pointed to by wstr or -1 if we have to do the allocation + */ +static inline BOOL CRYPT_ANSIToUnicode(LPCSTR str, LPWSTR* wstr, int wstrsize) +{ + int wcount; + + if (!str) + { + *wstr = NULL; + return TRUE; + } + wcount = MultiByteToWideChar(CP_ACP, 0, str, -1, NULL, 0); + if (wstrsize == -1) + *wstr = CRYPT_Alloc(wcount * sizeof(WCHAR)); + else + wcount = min( wcount, wstrsize/sizeof(WCHAR) ); + if (*wstr) + { + MultiByteToWideChar(CP_ACP, 0, str, -1, *wstr, wcount); + return TRUE; + } + SetLastError(ERROR_NOT_ENOUGH_MEMORY); + return FALSE; +} + +/* These next 2 functions are used by the VTableProvStruc structure */ +static BOOL CALLBACK CRYPT_VerifyImage(LPCSTR lpszImage, BYTE* pData) +{ + if (!lpszImage || !pData) + { + SetLastError(ERROR_INVALID_PARAMETER); + return FALSE; + } + + FIXME("(%s, %p): not verifying image\n", lpszImage, pData); + + return TRUE; +} + +static BOOL CALLBACK CRYPT_ReturnhWnd(HWND *phWnd) +{ + if (!phWnd) + return FALSE; + *phWnd = crypt_hWindow; + return TRUE; +} + +#define CRYPT_GetProvFunc(name) \ + if ( !(provider->pFuncs->p##name = (void*)GetProcAddress(provider->hModule, #name)) ) goto error +#define CRYPT_GetProvFuncOpt(name) \ + provider->pFuncs->p##name = (void*)GetProcAddress(provider->hModule, #name) +PCRYPTPROV CRYPT_LoadProvider(PSTR pImage) +{ + PCRYPTPROV provider; + DWORD errorcode = ERROR_NOT_ENOUGH_MEMORY; + + if ( !(provider = CRYPT_Alloc(sizeof(CRYPTPROV))) ) goto error; + if ( !(provider->pFuncs = CRYPT_Alloc(sizeof(PROVFUNCS))) ) goto error; + if ( !(provider->pVTable = CRYPT_Alloc(sizeof(VTableProvStruc))) ) goto error; + if ( !(provider->hModule = LoadLibraryA(pImage)) ) + { + errorcode = (GetLastError() == ERROR_FILE_NOT_FOUND) ? NTE_PROV_DLL_NOT_FOUND : NTE_PROVIDER_DLL_FAIL; + FIXME("Failed to load dll %s\n", debugstr_a(pImage)); + goto error; + } + provider->refcount = 1; + + errorcode = NTE_PROVIDER_DLL_FAIL; + CRYPT_GetProvFunc(CPAcquireContext); + CRYPT_GetProvFunc(CPCreateHash); + CRYPT_GetProvFunc(CPDecrypt); + CRYPT_GetProvFunc(CPDeriveKey); + CRYPT_GetProvFunc(CPDestroyHash); + CRYPT_GetProvFunc(CPDestroyKey); + CRYPT_GetProvFuncOpt(CPDuplicateHash); + CRYPT_GetProvFuncOpt(CPDuplicateKey); + CRYPT_GetProvFunc(CPEncrypt); + CRYPT_GetProvFunc(CPExportKey); + CRYPT_GetProvFunc(CPGenKey); + CRYPT_GetProvFunc(CPGenRandom); + CRYPT_GetProvFunc(CPGetHashParam); + CRYPT_GetProvFunc(CPGetKeyParam); + CRYPT_GetProvFunc(CPGetProvParam); + CRYPT_GetProvFunc(CPGetUserKey); + CRYPT_GetProvFunc(CPHashData); + CRYPT_GetProvFunc(CPHashSessionKey); + CRYPT_GetProvFunc(CPImportKey); + CRYPT_GetProvFunc(CPReleaseContext); + CRYPT_GetProvFunc(CPSetHashParam); + CRYPT_GetProvFunc(CPSetKeyParam); + CRYPT_GetProvFunc(CPSetProvParam); + CRYPT_GetProvFunc(CPSignHash); + CRYPT_GetProvFunc(CPVerifySignature); + + /* FIXME: Not sure what the pbContextInfo field is for. + * Does it need memory allocation? + */ + provider->pVTable->Version = 3; + provider->pVTable->pFuncVerifyImage = (FARPROC)CRYPT_VerifyImage; + provider->pVTable->pFuncReturnhWnd = (FARPROC)CRYPT_ReturnhWnd; + provider->pVTable->dwProvType = 0; + provider->pVTable->pbContextInfo = NULL; + provider->pVTable->cbContextInfo = 0; + provider->pVTable->pszProvName = NULL; + return provider; + +error: + SetLastError(errorcode); + if (provider) + { + if (provider->hModule) + FreeLibrary(provider->hModule); + CRYPT_Free(provider->pVTable); + CRYPT_Free(provider->pFuncs); + CRYPT_Free(provider); + } + return NULL; +} +#undef CRYPT_GetProvFunc +#undef CRYPT_GetProvFuncOpt + + +/********************************************************************** ******** + * CryptAcquireContextA (ADVAPI32.@) + * Acquire a crypto provider context handle. + * + * PARAMS + * phProv: Pointer to HCRYPTPROV for the output. + * pszContainer: Key Container Name + * pszProvider: Cryptographic Service Provider Name + * dwProvType: Crypto provider type to get a handle. + * dwFlags: flags for the operation + * + * RETURNS TRUE on success, FALSE on failure. + */ +BOOL WINAPI CryptAcquireContextA (HCRYPTPROV *phProv, LPCSTR pszContainer, + LPCSTR pszProvider, DWORD dwProvType, DWORD dwFlags) +{ + PCRYPTPROV pProv = NULL; + HKEY key; + PSTR imagepath = NULL, keyname = NULL, provname = NULL, temp = NULL; + BYTE* signature; + DWORD keytype, type, len; + ULONG r; + + TRACE("(%p, %s, %s, %ld, %08lx)\n", phProv, pszContainer, + pszProvider, dwProvType, dwFlags); + + if (dwProvType < 1 || dwProvType > MAXPROVTYPES) + { + SetLastError(NTE_BAD_PROV_TYPE); + return FALSE; + } + + if (!phProv) + { + SetLastError(ERROR_INVALID_PARAMETER); + return FALSE; + } + + if (!pszProvider || !*pszProvider) + { + /* No CSP name specified so try the user default CSP first + * then try the machine default CSP + */ + if ( !(keyname = CRYPT_GetTypeKeyName(dwProvType, TRUE)) ) { + TRACE("No provider registered for crypto provider type %ld.\n", dwProvType); + SetLastError(NTE_PROV_TYPE_NOT_DEF); + return FALSE; + } + if (RegOpenKeyA(HKEY_CURRENT_USER, keyname, &key)) + { + CRYPT_Free(keyname); + if ( !(keyname = CRYPT_GetTypeKeyName(dwProvType, FALSE)) ) { + TRACE("No type registered for crypto provider type %ld.\n", dwProvType); + RegCloseKey(key); + SetLastError(NTE_PROV_TYPE_NOT_DEF); + goto error; + } + if (RegOpenKeyA(HKEY_LOCAL_MACHINE, keyname, &key)) { + TRACE("Did not find registry entry of crypto provider for %s.\n", debugstr_a(keyname)); + CRYPT_Free(keyname); + RegCloseKey(key); + SetLastError(NTE_PROV_TYPE_NOT_DEF); + goto error; + } + } + CRYPT_Free(keyname); + r = RegQueryValueExA(key, "Name", NULL, &keytype, NULL, &len); + if( r != ERROR_SUCCESS || !len || keytype != REG_SZ) + { + TRACE("error %ld reading size of 'Name' from registry\n", r ); + RegCloseKey(key); + SetLastError(NTE_PROV_TYPE_ENTRY_BAD); + goto error; + } + if(!(provname = CRYPT_Alloc(len))) + { + RegCloseKey(key); + SetLastError(ERROR_NOT_ENOUGH_MEMORY); + goto error; + } + r = RegQueryValueExA(key, "Name", NULL, NULL, provname, &len); + if( r != ERROR_SUCCESS ) + { + TRACE("error %ld reading 'Name' from registry\n", r ); + RegCloseKey(key); + SetLastError(NTE_PROV_TYPE_ENTRY_BAD); + goto error; + } + RegCloseKey(key); + } else { + if ( !(provname = CRYPT_Alloc(strlen(pszProvider) +1)) ) + { + SetLastError(ERROR_NOT_ENOUGH_MEMORY); + goto error; + } + strcpy(provname, pszProvider); + } + + keyname = CRYPT_GetProvKeyName(provname); + r = RegOpenKeyA(HKEY_LOCAL_MACHINE, keyname, &key); + CRYPT_Free(keyname); + if (r != ERROR_SUCCESS) + { + SetLastError(NTE_KEYSET_NOT_DEF); + goto error; + } + len = sizeof(DWORD); + r = RegQueryValueExA(key, "Type", NULL, NULL, (BYTE*)&type, &len); + if (r != ERROR_SUCCESS) + { + SetLastError(NTE_PROV_TYPE_ENTRY_BAD); + goto error; + } + if (type != dwProvType) + { + TRACE("Crypto provider has wrong type (%ld vs expected %ld).\n", type, dwProvType); + SetLastError(NTE_PROV_TYPE_NO_MATCH); + goto error; + } + + r = RegQueryValueExA(key, "Image Path", NULL, &keytype, NULL, &len); + if ( r != ERROR_SUCCESS || keytype != REG_SZ) + { + TRACE("error %ld reading size of 'Image Path' from registry\n", r ); + RegCloseKey(key); + SetLastError(NTE_PROV_TYPE_ENTRY_BAD); + goto error; + } + if (!(temp = CRYPT_Alloc(len))) + { + RegCloseKey(key); + SetLastError(ERROR_NOT_ENOUGH_MEMORY); + goto error; + } + r = RegQueryValueExA(key, "Image Path", NULL, NULL, temp, &len); + if( r != ERROR_SUCCESS ) + { + TRACE("error %ld reading 'Image Path' from registry\n", r ); + RegCloseKey(key); + SetLastError(NTE_PROV_TYPE_ENTRY_BAD); + goto error; + } + + r = RegQueryValueExA(key, "Signature", NULL, &keytype, NULL, &len); + if ( r == ERROR_SUCCESS && keytype == REG_BINARY ) + { + if (!(signature = CRYPT_Alloc(len))) + { + RegCloseKey(key); + SetLastError(ERROR_NOT_ENOUGH_MEMORY); + goto error; + } + r = RegQueryValueExA(key, "Signature", NULL, NULL, signature, &len); + if ( r != ERROR_SUCCESS ) + { + TRACE("error %ld reading 'Signature'\n", r ); + CRYPT_Free(signature); + RegCloseKey(key); + SetLastError(NTE_PROV_TYPE_ENTRY_BAD); + goto error; + } + } + else + { + r = RegQueryValueExA(key, "SigInFile", NULL, &keytype, NULL, &len); + if (r != ERROR_SUCCESS) + { + TRACE("error %ld reading size of 'SigInFile'\n", r ); + RegCloseKey(key); + SetLastError(NTE_PROV_TYPE_ENTRY_BAD); + goto error; + } + else + { + /* FIXME: The presence of the SigInFile value indicates the + * provider's signature is in its resources, so need to read it. + * But since CRYPT_VerifyImage is stubbed, provide any old thing + * for now. + */ + if (!(signature = CRYPT_Alloc(1))) + { + RegCloseKey(key); + SetLastError(ERROR_NOT_ENOUGH_MEMORY); + goto error; + } + } + } + RegCloseKey(key); + len = ExpandEnvironmentStringsA(temp, NULL, 0); + if ( !(imagepath = CRYPT_Alloc(len)) ) + { + CRYPT_Free(signature); + SetLastError(ERROR_NOT_ENOUGH_MEMORY); + goto error; + } + if (!ExpandEnvironmentStringsA(temp, imagepath, len)) + { + CRYPT_Free(signature); + /* ExpandEnvironmentStrings will call SetLastError */ + goto error; + } + + if (!CRYPT_VerifyImage(imagepath, signature)) + { + CRYPT_Free(signature); + SetLastError(NTE_SIGNATURE_FILE_BAD); + goto error; + } + pProv = CRYPT_LoadProvider(imagepath); + CRYPT_Free(signature); + if (!pProv) { + /* CRYPT_LoadProvider calls SetLastError */ + goto error; + } + pProv->pVTable->dwProvType = dwProvType; + pProv->pVTable->pszProvName = provname; + if (pProv->pFuncs->pCPAcquireContext(&pProv->hPrivate, (CHAR*)pszContainer, dwFlags, pProv->pVTable)) + { + /* MSDN: When this flag is set, the value returned in phProv is undefined, + * and thus, the CryptReleaseContext function need not be called afterwards. + * Therefore, we must clean up everything now. + */ + if (dwFlags & CRYPT_DELETEKEYSET) + { + FreeLibrary(pProv->hModule); + CRYPT_Free(provname); + CRYPT_Free(pProv->pFuncs); + CRYPT_Free(pProv); + } else { + *phProv = (HCRYPTPROV)pProv; + } + CRYPT_Free(temp); + CRYPT_Free(imagepath); + return TRUE; + } + /* FALLTHROUGH TO ERROR IF FALSE - CSP internal error! */ +error: + if (pProv) + { + if (pProv->hModule) + FreeLibrary(pProv->hModule); + if (pProv->pVTable) + CRYPT_Free(pProv->pVTable); + if (pProv->pFuncs) + CRYPT_Free(pProv->pFuncs); + CRYPT_Free(pProv); + } + if (provname) + CRYPT_Free(provname); + if (temp) + CRYPT_Free(temp); + if (imagepath) + CRYPT_Free(imagepath); + return FALSE; +} + +/********************************************************************** ******** + * CryptAcquireContextW (ADVAPI32.@) + * + * see CryptAcquireContextA + */ +BOOL WINAPI CryptAcquireContextW (HCRYPTPROV *phProv, LPCWSTR pszContainer, + LPCWSTR pszProvider, DWORD dwProvType, DWORD dwFlags) +{ + PSTR pProvider = NULL, pContainer = NULL; + BOOL ret = FALSE; + + TRACE("(%p, %s, %s, %ld, %08lx)\n", phProv, debugstr_w(pszContainer), + debugstr_w(pszProvider), dwProvType, dwFlags); + + if ( !CRYPT_UnicodeToANSI(pszContainer, &pContainer, -1) ) + CRYPT_ReturnLastError(ERROR_NOT_ENOUGH_MEMORY); + if ( !CRYPT_UnicodeToANSI(pszProvider, &pProvider, -1) ) + { + CRYPT_Free(pContainer); + CRYPT_ReturnLastError(ERROR_NOT_ENOUGH_MEMORY); + } + + ret = CryptAcquireContextA(phProv, pContainer, pProvider, dwProvType, dwFlags); + + if (pContainer) + CRYPT_Free(pContainer); + if (pProvider) + CRYPT_Free(pProvider); + + return ret; +} + +/********************************************************************** ******** + * CryptContextAddRef (ADVAPI32.@) + * + * Increases reference count of a cryptographic service provider handle + * by one. + * + * PARAMS + * hProv [I] Handle to the CSP whose reference is being incremented. + * pdwReserved [IN] Reserved for future use and must be NULL. + * dwFlags [I] Reserved for future use and must be NULL. + * + * RETURNS + * Success: TRUE + * Failure: FALSE + */ +BOOL WINAPI CryptContextAddRef (HCRYPTPROV hProv, DWORD *pdwReserved, DWORD dwFlags) +{ + PCRYPTPROV pProv = (PCRYPTPROV)hProv; + + TRACE("(0x%lx, %p, %08lx)\n", hProv, pdwReserved, dwFlags); + + if (!pProv) + { + SetLastError(NTE_BAD_UID); + return FALSE; + } + + pProv->refcount++; + return TRUE; +} + +/********************************************************************** ******** + * CryptReleaseContext (ADVAPI32.@) + * + * Releases the handle of a CSP. Reference count is decreased. + * + * PARAMS + * hProv [I] Handle of a CSP. + * dwFlags [I] Reserved for future use and must be NULL. + * + * RETURNS + * Success: TRUE + * Failure: FALSE + */ +BOOL WINAPI CryptReleaseContext (HCRYPTPROV hProv, DWORD dwFlags) +{ + PCRYPTPROV pProv = (PCRYPTPROV)hProv; + BOOL ret = TRUE; + + TRACE("(0x%lx, %08ld)\n", hProv, dwFlags); + + if (!pProv) + { + SetLastError(NTE_BAD_UID); + return FALSE; + } + + pProv->refcount--; + if (pProv->refcount <= 0) + { + ret = pProv->pFuncs->pCPReleaseContext(pProv->hPrivate, dwFlags); + FreeLibrary(pProv->hModule); +#if 0 + CRYPT_Free(pProv->pVTable->pContextInfo); +#endif + CRYPT_Free(pProv->pVTable->pszProvName); + CRYPT_Free(pProv->pVTable); + CRYPT_Free(pProv->pFuncs); + CRYPT_Free(pProv); + } + return ret; +} + +/********************************************************************** ******** + * CryptGenRandom (ADVAPI32.@) + * + * Fills a buffer with cryptographically random bytes. + * + * PARAMS + * hProv [I] Handle of a CSP. + * dwLen [I] Number of bytes to generate. + * pbBuffer [I/O] Buffer to contain random bytes. + * + * RETURNS + * Success: TRUE + * Failure: FALSE + * + * NOTES + * pdBuffer must be at least dwLen bytes long. + */ +BOOL WINAPI CryptGenRandom (HCRYPTPROV hProv, DWORD dwLen, BYTE *pbBuffer) +{ + PCRYPTPROV prov = (PCRYPTPROV)hProv; + + TRACE("(0x%lx, %ld, %p)\n", hProv, dwLen, pbBuffer); + + if (!hProv) + CRYPT_ReturnLastError(ERROR_INVALID_HANDLE); + + return prov->pFuncs->pCPGenRandom(prov->hPrivate, dwLen, pbBuffer); +} + +/********************************************************************** ******** + * CryptCreateHash (ADVAPI32.@) + * + * Initiates the hashing of a stream of data. + * + * PARAMS + * hProv [I] Handle of a CSP. + * Algid [I] Identifies the hash algorithm to use. + * hKey [I] Key for the hash (if required). + * dwFlags [I] Reserved for future use and must be NULL. + * phHash [O] Address of the future handle to the new hash object. + * + * RETURNS + * Success: TRUE + * Failure: FALSE + * + * NOTES + * If the algorithm is a keyed hash, hKey is the key. + */ +BOOL WINAPI CryptCreateHash (HCRYPTPROV hProv, ALG_ID Algid, HCRYPTKEY hKey, + DWORD dwFlags, HCRYPTHASH *phHash) +{ + PCRYPTPROV prov = (PCRYPTPROV)hProv; + PCRYPTKEY key = (PCRYPTKEY)hKey; + PCRYPTHASH hash; + + TRACE("(0x%lx, 0x%x, 0x%lx, %08lx, %p)\n", hProv, Algid, hKey, dwFlags, phHash); + + if (!prov) + CRYPT_ReturnLastError(ERROR_INVALID_HANDLE); + if (!phHash) + CRYPT_ReturnLastError(ERROR_INVALID_PARAMETER); + if (dwFlags) + CRYPT_ReturnLastError(NTE_BAD_FLAGS); + if ( !(hash = CRYPT_Alloc(sizeof(CRYPTHASH))) ) + CRYPT_ReturnLastError(ERROR_NOT_ENOUGH_MEMORY); + + hash->pProvider = prov; + + if (prov->pFuncs->pCPCreateHash(prov->hPrivate, Algid, + key ? key->hPrivate : 0, 0, &hash->hPrivate)) + { + *phHash = (HCRYPTHASH)hash; + return TRUE; + } + + /* CSP error! */ + CRYPT_Free(hash); + *phHash = 0; + return FALSE; +} + +/********************************************************************** ******** + * CryptDecrypt (ADVAPI32.@) + * + * Decrypts data encrypted by CryptEncrypt. + * + * PARAMS + * hKey [I] Handle to the decryption key. + * hHash [I] Handle to a hash object. + * Final [I] TRUE if this is the last section to be decrypted. + * dwFlags [I] Reserved for future use. Can be CRYPT_OAEP. + * pbData [I/O] Buffer that holds the encrypted data. Holds decrypted + * data on return + * pdwDataLen [I/O] Length of pbData before and after the call. + * + * RETURNS + * Success: TRUE + * Failure: FALSE + */ +BOOL WINAPI CryptDecrypt (HCRYPTKEY hKey, HCRYPTHASH hHash, BOOL Final, + DWORD dwFlags, BYTE *pbData, DWORD *pdwDataLen) +{ + PCRYPTPROV prov; + PCRYPTKEY key = (PCRYPTKEY)hKey; + PCRYPTHASH hash = (PCRYPTHASH)hHash; + + TRACE("(0x%lx, 0x%lx, %d, %08lx, %p, %p)\n", hKey, hHash, Final, dwFlags, pbData, pdwDataLen); + + if (!key || !pbData || !pdwDataLen) + CRYPT_ReturnLastError(ERROR_INVALID_PARAMETER); + + prov = key->pProvider; + return prov->pFuncs->pCPDecrypt(prov->hPrivate, key->hPrivate, hash ? hash->hPrivate : 0, + Final, dwFlags, pbData, pdwDataLen); +} + +/********************************************************************** ******** + * CryptDeriveKey (ADVAPI32.@) + * + * Generates session keys derived from a base data value. + * + * PARAMS + * hProv [I] Handle to a CSP. + * Algid [I] Identifies the symmetric encryption algorithm to use. + * hBaseData [I] Handle to a hash object. + * dwFlags [I] Type of key to generate. + * phKey [I/O] Address of the newly generated key. + * + * RETURNS + * Success: TRUE + * Failure: FALSE + */ +BOOL WINAPI CryptDeriveKey (HCRYPTPROV hProv, ALG_ID Algid, HCRYPTHASH hBaseData, + DWORD dwFlags, HCRYPTKEY *phKey) +{ + PCRYPTPROV prov = (PCRYPTPROV)hProv; + PCRYPTHASH hash = (PCRYPTHASH)hBaseData; + PCRYPTKEY key; + + TRACE("(0x%lx, 0x%08x, 0x%lx, 0x%08lx, %p)\n", hProv, Algid, hBaseData, dwFlags, phKey); + + if (!prov || !hash) + CRYPT_ReturnLastError(ERROR_INVALID_HANDLE); + if (!phKey) + CRYPT_ReturnLastError(ERROR_INVALID_PARAMETER); + if ( !(key = CRYPT_Alloc(sizeof(CRYPTKEY))) ) + CRYPT_ReturnLastError(ERROR_NOT_ENOUGH_MEMORY); + + key->pProvider = prov; + if (prov->pFuncs->pCPDeriveKey(prov->hPrivate, Algid, hash->hPrivate, dwFlags, &key->hPrivate)) + { + *phKey = (HCRYPTKEY)key; + return TRUE; + } + + /* CSP error! */ + CRYPT_Free(key); + *phKey = 0; + return FALSE; +} + +/********************************************************************** ******** + * CryptDestroyHash (ADVAPI32.@) + * + * Destroys the hash object referenced by hHash. + * + * PARAMS + * hHash [I] Handle of the hash object to be destroyed. + * + * RETURNS + * Success: TRUE + * Failure: FALSE + */ +BOOL WINAPI CryptDestroyHash (HCRYPTHASH hHash) +{ + PCRYPTHASH hash = (PCRYPTHASH)hHash; + PCRYPTPROV prov; + BOOL ret; + + TRACE("(0x%lx)\n", hHash); + + if (!hash) + CRYPT_ReturnLastError(ERROR_INVALID_HANDLE); + + prov = hash->pProvider; + ret = prov->pFuncs->pCPDestroyHash(prov->hPrivate, hash->hPrivate); + CRYPT_Free(hash); + return ret; +} + +/********************************************************************** ******** + * CryptDestroyKey (ADVAPI32.@) + * + * Releases the handle referenced by hKey. + * + * PARAMS + * hKey [I] Handle of the key to be destroyed. + * + * RETURNS + * Success: TRUE + * Failure: FALSE + */ +BOOL WINAPI CryptDestroyKey (HCRYPTKEY hKey) +{ + PCRYPTKEY key = (PCRYPTKEY)hKey; + PCRYPTPROV prov; + BOOL ret; + + TRACE("(0x%lx)\n", hKey); + + if (!key) + CRYPT_ReturnLastError(ERROR_INVALID_HANDLE); + + prov = key->pProvider; + ret = prov->pFuncs->pCPDestroyKey(prov->hPrivate, key->hPrivate); + CRYPT_Free(key); + return ret; +} + +/********************************************************************** ******** + * CryptDuplicateHash (ADVAPI32.@) + * + * Duplicates a hash. + * + * PARAMS + * hHash [I] Handle to the hash to be copied. + * pdwReserved [I] Reserved for future use and must be zero. + * dwFlags [I] Reserved for future use and must be zero. + * phHash [O] Address of the handle to receive the copy. + * + * RETURNS + * Success: TRUE + * Failure: FALSE + */ +BOOL WINAPI CryptDuplicateHash (HCRYPTHASH hHash, DWORD *pdwReserved, + DWORD dwFlags, HCRYPTHASH *phHash) +{ + PCRYPTPROV prov; + PCRYPTHASH orghash, newhash; + + TRACE("(0x%lx, %p, %08ld, %p)\n", hHash, pdwReserved, dwFlags, phHash); + + orghash = (PCRYPTHASH)hHash; + if (!orghash || pdwReserved || !phHash) + CRYPT_ReturnLastError(ERROR_INVALID_PARAMETER); + + prov = orghash->pProvider; + if (!prov->pFuncs->pCPDuplicateHash) + CRYPT_ReturnLastError(ERROR_CALL_NOT_IMPLEMENTED); + + if ( !(newhash = CRYPT_Alloc(sizeof(CRYPTHASH))) ) + CRYPT_ReturnLastError(ERROR_NOT_ENOUGH_MEMORY); + + newhash->pProvider = prov; + if (prov->pFuncs->pCPDuplicateHash(prov->hPrivate, orghash->hPrivate, pdwReserved, dwFlags, &newhash->hPrivate)) + { + *phHash = (HCRYPTHASH)newhash; + return TRUE; + } + CRYPT_Free(newhash); + return FALSE; +} + +/********************************************************************** ******** + * CryptDuplicateKey (ADVAPI32.@) + * + * Duplicate a key and the key's state. + * + * PARAMS + * hKey [I] Handle of the key to copy. + * pdwReserved [I] Reserved for future use and must be NULL. + * dwFlags [I] Reserved for future use and must be zero. + * phKey [I] Address of the handle to the duplicated key. + * + * RETURNS + * Success: TRUE + * Failure: FALSE + */ +BOOL WINAPI CryptDuplicateKey (HCRYPTKEY hKey, DWORD *pdwReserved, DWORD dwFlags, HCRYPTKEY *phKey) +{ + PCRYPTPROV prov; + PCRYPTKEY orgkey, newkey; + + TRACE("(0x%lx, %p, %08ld, %p)\n", hKey, pdwReserved, dwFlags, phKey); + + orgkey = (PCRYPTKEY)hKey; + if (!orgkey || pdwReserved || !phKey) + CRYPT_ReturnLastError(ERROR_INVALID_PARAMETER); + + prov = orgkey->pProvider; + if (!prov->pFuncs->pCPDuplicateKey) + CRYPT_ReturnLastError(ERROR_CALL_NOT_IMPLEMENTED); + + if ( !(newkey = CRYPT_Alloc(sizeof(CRYPTKEY))) ) + CRYPT_ReturnLastError(ERROR_NOT_ENOUGH_MEMORY); + + newkey->pProvider = prov; + if (prov->pFuncs->pCPDuplicateKey(prov->hPrivate, orgkey->hPrivate, pdwReserved, dwFlags, &newkey->hPrivate)) + { + *phKey = (HCRYPTKEY)newkey; + return TRUE; + } + CRYPT_Free(newkey); + return FALSE; +} + +/********************************************************************** ******** + * CryptEncrypt (ADVAPI32.@) + * + * Encrypts data. + * + * PARAMS + * hKey [I] Handle to the enryption key. + * hHash [I] Handle to a hash object. + * Final [I] TRUE if this is the last section to encrypt. + * dwFlags [I] Can be CRYPT_OAEP. + * pbData [I/O] Data to be encrypted. Contains encrypted data after call. + * pdwDataLen [I/O] Length of the data to encrypt. Contains the length of the + * encrypted data after call. + * dwBufLen [I] Length of the input pbData buffer. + * + * RETURNS + * Success: TRUE + * Failure: FALSE + * + * NOTES + * If pbData is NULL, CryptEncrypt determines stores the number of bytes + * required for the returned data in pdwDataLen. + */ +BOOL WINAPI CryptEncrypt (HCRYPTKEY hKey, HCRYPTHASH hHash, BOOL Final, + DWORD dwFlags, BYTE *pbData, DWORD *pdwDataLen, DWORD dwBufLen) +{ + PCRYPTPROV prov; + PCRYPTKEY key = (PCRYPTKEY)hKey; + PCRYPTHASH hash = (PCRYPTHASH)hHash; + + TRACE("(0x%lx, 0x%lx, %d, %08ld, %p, %p, %ld)\n", hKey, hHash, Final, dwFlags, pbData, pdwDataLen, dwBufLen); + + if (!key || !pdwDataLen) + CRYPT_ReturnLastError(ERROR_INVALID_PARAMETER); + + prov = key->pProvider; + return prov->pFuncs->pCPEncrypt(prov->hPrivate, key->hPrivate, hash ? hash->hPrivate : 0, + Final, dwFlags, pbData, pdwDataLen, dwBufLen); +} + +/********************************************************************** ******** + * CryptEnumProvidersW (ADVAPI32.@) + * + * Returns the next availabe CSP. + * + * PARAMS + * dwIndex [I] Index of the next provider to be enumerated. + * pdwReserved [I] Reserved for future use and must be NULL. + * dwFlags [I] Reserved for future use and must be zero. + * pdwProvType [O] DWORD designating the type of the provider. + * pszProvName [O] Buffer that receives data from the provider. + * pcbProvName [I/O] Specifies the size of pszProvName. Contains the number + * of bytes stored in the buffer on return. + * + * RETURNS + * Success: TRUE + * Failure: FALSE + * + * NOTES + * If pszProvName is NULL, CryptEnumProvidersW sets the size of the name + * for memory allocation purposes. + */ +BOOL WINAPI CryptEnumProvidersW (DWORD dwIndex, DWORD *pdwReserved, + DWORD dwFlags, DWORD *pdwProvType, LPWSTR pszProvName, DWORD *pcbProvName) +{ + HKEY hKey; + + static const WCHAR providerW[] = { + 'S','o','f','t','w','a','r','e','\', + 'M','i','c','r','o','s','o','f','t','\', + 'C','r','y','p','t','o','g','r','a','p','h','y','\', + 'D','e','f','a','u','l','t','s','\', + 'P','r','o','v','i','d','e','r',0 + }; + + static const WCHAR typeW[] = {'T','y','p','e',0}; + + TRACE("(%ld, %p, %ld, %p, %p, %p)\n", dwIndex, pdwReserved, dwFlags, + pdwProvType, pszProvName, pcbProvName); + + if (pdwReserved || !pcbProvName) CRYPT_ReturnLastError(ERROR_INVALID_PARAMETER); + if (dwFlags) CRYPT_ReturnLastError(NTE_BAD_FLAGS); + + if (RegOpenKeyW(HKEY_LOCAL_MACHINE, providerW, &hKey)) + CRYPT_ReturnLastError(NTE_FAIL); + + if (!pszProvName) + { + DWORD numkeys; + WCHAR *provNameW; [truncated at 1000 lines; 2100 more skipped]