From 4173776e7bf2eea9e25208cedca2fef17dd433d4 Mon Sep 17 00:00:00 2001 From: Thomas Bluemel Date: Sat, 11 Dec 2004 00:21:33 +0000 Subject: [PATCH] port crypt and trustee support from Wine. Patch by Steven Edwards. svn path=/trunk/; revision=12007 --- reactos/lib/advapi32/advapi32.def | 73 +- reactos/lib/advapi32/advapi32.h | 1 + reactos/lib/advapi32/crypt/.cvsignore | 2 + reactos/lib/advapi32/crypt/crypt.c | 1922 +++++++++++++++++++++ reactos/lib/advapi32/crypt/crypt.h | 86 + reactos/lib/advapi32/crypt/crypt_des.c | 290 ++++ reactos/lib/advapi32/crypt/crypt_lmhash.c | 60 + reactos/lib/advapi32/crypt/crypt_md4.c | 270 +++ reactos/lib/advapi32/crypt/crypt_md5.c | 280 +++ reactos/lib/advapi32/crypt/crypt_sha.c | 188 ++ reactos/lib/advapi32/makefile | 16 +- reactos/lib/advapi32/misc/sysfunc.c | 16 +- reactos/lib/advapi32/sec/trustee.c | 68 + reactos/lib/advapi32/token/token.c | 12 +- 14 files changed, 3225 insertions(+), 59 deletions(-) create mode 100644 reactos/lib/advapi32/crypt/.cvsignore create mode 100644 reactos/lib/advapi32/crypt/crypt.c create mode 100644 reactos/lib/advapi32/crypt/crypt.h create mode 100644 reactos/lib/advapi32/crypt/crypt_des.c create mode 100644 reactos/lib/advapi32/crypt/crypt_lmhash.c create mode 100644 reactos/lib/advapi32/crypt/crypt_md4.c create mode 100644 reactos/lib/advapi32/crypt/crypt_md5.c create mode 100644 reactos/lib/advapi32/crypt/crypt_sha.c create mode 100644 reactos/lib/advapi32/sec/trustee.c diff --git a/reactos/lib/advapi32/advapi32.def b/reactos/lib/advapi32/advapi32.def index 3580124fb2c..7d1485818af 100644 --- a/reactos/lib/advapi32/advapi32.def +++ b/reactos/lib/advapi32/advapi32.def @@ -1,4 +1,4 @@ -; $Id: advapi32.def,v 1.25 2004/11/21 20:14:36 gdalsnes Exp $ +; $Id: advapi32.def,v 1.26 2004/12/11 00:21:33 weiden Exp $ ; ; advapi32.def ; @@ -6,6 +6,9 @@ ; LIBRARY advapi32.dll EXPORTS +A_SHAFinal@8 +A_SHAInit@4 +A_SHAUpdate@12 AbortSystemShutdownA@4 AbortSystemShutdownW@4 AccessCheck@32 @@ -36,10 +39,10 @@ BackupEventLogW@8 ;BuildImpersonateTrusteeW@8 ;BuildSecurityDescriptorA@36 ;BuildSecurityDescriptorW@36 -;BuildTrusteeWithNameA@8 -;BuildTrusteeWithNameW@8 -;BuildTrusteeWithSidA@8 -;BuildTrusteeWithSidW@8 +BuildTrusteeWithNameA@8 +BuildTrusteeWithNameW@8 +BuildTrusteeWithSidA@8 +BuildTrusteeWithSidW@8 ChangeServiceConfigA@44 ChangeServiceConfigW@44 ClearEventLogA@8 @@ -55,34 +58,34 @@ CreateProcessAsUserA@44 CreateProcessAsUserW@44 CreateServiceA@52 CreateServiceW@52 -;CryptAcquireContextA@20 -;CryptAcquireContextW@20 -;CryptContextAddRef@12 -;CryptCreateHash@20 -;CryptDecrypt@24 -;CryptDeriveKey@20 -;CryptDestroyHash@4 -;CryptDestroyKey@4 -;CryptEncrypt@28 -;CryptExportKey@24 -;CryptGenKey@16 -;CryptGenRandom@12 -;CryptGetHashParam@20 -;CryptGetKeyParam@20 -;CryptGetProvParam@20 -;CryptGetUserKey@12 -;CryptHashData@16 -;CryptHashSessionKey@12 -;CryptImportKey@24 -;CryptReleaseContext@8 -;CryptSetHashParam@16 -;CryptSetKeyParam@16 -;CryptSetProvParam@16 -;CryptSetProviderA@8 -;CryptSetProviderW@8 -;CryptSignHashA@24 +CryptAcquireContextA@20 +CryptAcquireContextW@20 +CryptContextAddRef@12 +CryptCreateHash@20 +CryptDecrypt@24 +CryptDeriveKey@20 +CryptDestroyHash@4 +CryptDestroyKey@4 +CryptEncrypt@28 +CryptExportKey@24 +CryptGenKey@16 +CryptGenRandom@12 +CryptGetHashParam@20 +CryptGetKeyParam@20 +CryptGetProvParam@20 +CryptGetUserKey@12 +CryptHashData@16 +CryptHashSessionKey@12 +CryptImportKey@24 +CryptReleaseContext@8 +CryptSetHashParam@16 +CryptSetKeyParam@16 +CryptSetProvParam@16 +CryptSetProviderA@8 +CryptSetProviderW@8 +CryptSignHashA@24 ;CryptSignHashW@24 -;CryptVerifySignatureA@24 +CryptVerifySignatureA@24 ;CryptVerifySignatureW@24 DeleteAce@8 DeleteService@4 @@ -259,6 +262,12 @@ LsaQueryInformationPolicy@12 MakeAbsoluteSD@44 MakeSelfRelativeSD@12 MapGenericMask@8 +MD4Final@4 +MD4Init@4 +MD4Update@12 +MD5Final@4 +MD5Init@4 +MD5Update@12 ;NTAccessMaskToProvAccessRights@12 ;NotifyBootConfigStatus@4 NotifyChangeEventLog@8 diff --git a/reactos/lib/advapi32/advapi32.h b/reactos/lib/advapi32/advapi32.h index 207820132db..b1cd1513253 100644 --- a/reactos/lib/advapi32/advapi32.h +++ b/reactos/lib/advapi32/advapi32.h @@ -8,3 +8,4 @@ #include #include #include +#include diff --git a/reactos/lib/advapi32/crypt/.cvsignore b/reactos/lib/advapi32/crypt/.cvsignore new file mode 100644 index 00000000000..c6ebd86daea --- /dev/null +++ b/reactos/lib/advapi32/crypt/.cvsignore @@ -0,0 +1,2 @@ +*.o +.*.d diff --git a/reactos/lib/advapi32/crypt/crypt.c b/reactos/lib/advapi32/crypt/crypt.c new file mode 100644 index 00000000000..28a639fdeed --- /dev/null +++ b/reactos/lib/advapi32/crypt/crypt.c @@ -0,0 +1,1922 @@ +/* + * 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 "wine/config.h" +#include "wine/port.h" + +#include +#include +#include +#include + +#include "wine/unicode.h" +#include "crypt.h" +#include "winnls.h" +#include "wincrypt.h" +#include "windef.h" +#include "winerror.h" +#include "winreg.h" +#include "winbase.h" +//#include "winuser.h" +#include "wine/debug.h" + +typedef LONG (CALLBACK *PVECTORED_EXCEPTION_HANDLER)( + struct _EXCEPTION_POINTERS *ExceptionInfo + ); + +#include "wine/winternl.h" +#include "wine/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); + count = count < strsize ? count : strsize; + if (strsize == -1) + *str = CRYPT_Alloc(count * sizeof(CHAR)); + 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); + wcount = wcount < wstrsize/sizeof(WCHAR) ? wcount : wstrsize/sizeof(WCHAR); + if (wstrsize == -1) + *wstr = CRYPT_Alloc(wcount * 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; + + RegQueryInfoKeyW(hKey, NULL, NULL, NULL, &numkeys, pcbProvName, + NULL, NULL, NULL, NULL, NULL, NULL); + + if (!(provNameW = CRYPT_Alloc(*pcbProvName * sizeof(WCHAR)))) + CRYPT_ReturnLastError(ERROR_NOT_ENOUGH_MEMORY); + + RegEnumKeyExW(hKey, dwIndex, provNameW, pcbProvName, NULL, NULL, NULL, NULL); + (*pcbProvName)++; + *pcbProvName *= sizeof(WCHAR); + + CRYPT_Free(provNameW); + + if (dwIndex >= numkeys) + CRYPT_ReturnLastError(ERROR_NO_MORE_ITEMS); + } else { + DWORD size = sizeof(DWORD); + DWORD result; + HKEY subkey; + + result = RegEnumKeyW(hKey, dwIndex, pszProvName, *pcbProvName / sizeof(WCHAR)); + if (result) + CRYPT_ReturnLastError(result); + if (RegOpenKeyW(hKey, pszProvName, &subkey)) + return FALSE; + if (RegQueryValueExW(subkey, typeW, NULL, NULL, (BYTE*)pdwProvType, &size)) + return FALSE; + RegCloseKey(subkey); + } + RegCloseKey(hKey); + return TRUE; +} + +/****************************************************************************** + * CryptEnumProvidersA (ADVAPI32.@) + * + * see CryptEnumProvidersW + */ +BOOL WINAPI CryptEnumProvidersA (DWORD dwIndex, DWORD *pdwReserved, + DWORD dwFlags, DWORD *pdwProvType, LPSTR pszProvName, DWORD *pcbProvName) +{ + PWSTR str = NULL; + DWORD strlen; + BOOL ret; /* = FALSE; */ + + TRACE("(%ld, %p, %08ld, %p, %p, %p)\n", dwIndex, pdwReserved, dwFlags, + pdwProvType, pszProvName, pcbProvName); + + strlen = *pcbProvName * sizeof(WCHAR); + if ( pszProvName && !(str = CRYPT_Alloc(strlen)) ) + CRYPT_ReturnLastError(ERROR_NOT_ENOUGH_MEMORY); + ret = CryptEnumProvidersW(dwIndex, pdwReserved, dwFlags, pdwProvType, str, &strlen); + if (str) + { + CRYPT_UnicodeToANSI(str, &pszProvName, *pcbProvName); + CRYPT_Free(str); + } + *pcbProvName = strlen / sizeof(WCHAR); /* FIXME: not correct */ + return ret; +} + +/****************************************************************************** + * CryptEnumProviderTypesA (ADVAPI32i.@) + * + * Retrieves the next type of CSP supported. + * + * 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. + * pszTypeName [O] Buffer that receives data from the provider type. + * pcbTypeName [I/O] Specifies the size of pszTypeName. Contains the number + * of bytes stored in the buffer on return. + * + * RETURNS + * Success: TRUE + * Failure: FALSE + * + * NOTES + * If pszTypeName is NULL, CryptEnumProviderTypesA sets the size of the name + * for memory allocation purposes. + */ +BOOL WINAPI CryptEnumProviderTypesA (DWORD dwIndex, DWORD *pdwReserved, + DWORD dwFlags, DWORD *pdwProvType, LPSTR pszTypeName, DWORD *pcbTypeName) +{ + HKEY hKey, hSubkey; + DWORD keylen, numkeys, dwType; + PSTR keyname, ch; + DWORD result; + + TRACE("(%ld, %p, %08ld, %p, %p, %p)\n", dwIndex, pdwReserved, + dwFlags, pdwProvType, pszTypeName, pcbTypeName); + + if (pdwReserved || !pdwProvType || !pcbTypeName) + CRYPT_ReturnLastError(ERROR_INVALID_PARAMETER); + if (dwFlags) CRYPT_ReturnLastError(NTE_BAD_FLAGS); + + if (RegOpenKeyA(HKEY_LOCAL_MACHINE, "Software\\Microsoft\\Cryptography\\Defaults\\Provider Types", &hKey)) + return FALSE; + + RegQueryInfoKeyA(hKey, NULL, NULL, NULL, &numkeys, &keylen, NULL, NULL, NULL, NULL, NULL, NULL); + if (dwIndex >= numkeys) + CRYPT_ReturnLastError(ERROR_NO_MORE_ITEMS); + keylen++; + if ( !(keyname = CRYPT_Alloc(keylen)) ) + CRYPT_ReturnLastError(ERROR_NOT_ENOUGH_MEMORY); + if ( RegEnumKeyA(hKey, dwIndex, keyname, keylen) ) { + CRYPT_Free(keyname); + return FALSE; + } + RegOpenKeyA(hKey, keyname, &hSubkey); + ch = keyname + strlen(keyname); + /* Convert "Type 000" to 0, etc/ */ + *pdwProvType = *(--ch) - '0'; + *pdwProvType += (*(--ch) - '0') * 10; + *pdwProvType += (*(--ch) - '0') * 100; + CRYPT_Free(keyname); + + result = RegQueryValueExA(hSubkey, "TypeName", NULL, &dwType, pszTypeName, pcbTypeName); + if (result) + CRYPT_ReturnLastError(result); + + RegCloseKey(hSubkey); + RegCloseKey(hKey); + return TRUE; +} + +/****************************************************************************** + * CryptEnumProviderTypesW (ADVAPI32.@) + * + * see CryptEnumProviderTypesA + */ +BOOL WINAPI CryptEnumProviderTypesW (DWORD dwIndex, DWORD *pdwReserved, + DWORD dwFlags, DWORD *pdwProvType, LPWSTR pszTypeName, DWORD *pcbTypeName) +{ + PSTR str = NULL; + DWORD strlen; + BOOL ret; + + TRACE("(%ld, %p, %08ld, %p, %p, %p)\n", dwIndex, pdwReserved, dwFlags, + pdwProvType, pszTypeName, pcbTypeName); + strlen = *pcbTypeName / sizeof(WCHAR); + if ( pszTypeName && !(str = CRYPT_Alloc(strlen)) ) + CRYPT_ReturnLastError(ERROR_NOT_ENOUGH_MEMORY); + ret = CryptEnumProviderTypesA(dwIndex, pdwReserved, dwFlags, pdwProvType, str, &strlen); + if (str) + { + CRYPT_ANSIToUnicode(str, &pszTypeName, *pcbTypeName); + CRYPT_Free(str); + } + *pcbTypeName = strlen * sizeof(WCHAR); + return ret; +} + +/****************************************************************************** + * CryptExportKey (ADVAPI32.@) + * + * Exports a cryptographic key from a CSP. + * + * PARAMS + * hKey [I] Handle to the key to export. + * hExpKey [I] Handle to a cryptographic key of the end user. + * dwBlobType [I] Type of BLOB to be exported. + * dwFlags [I] CRYPT_DESTROYKEY/SSL2_FALLBACK/OAEP. + * pbData [O] Buffer to receive BLOB data. + * pdwDataLen [I/O] Specifies the size of pbData. + * + * RETURNS + * Success: TRUE + * Failure: FALSE + * + * NOTES + * if pbData is NULL, CryptExportKey sets pdwDataLen as the size of the + * buffer needed to hold the BLOB. + */ +BOOL WINAPI CryptExportKey (HCRYPTKEY hKey, HCRYPTKEY hExpKey, DWORD dwBlobType, + DWORD dwFlags, BYTE *pbData, DWORD *pdwDataLen) +{ + PCRYPTPROV prov; + PCRYPTKEY key = (PCRYPTKEY)hKey, expkey = (PCRYPTKEY)hExpKey; + + TRACE("(0x%lx, 0x%lx, %ld, %08ld, %p, %p)\n", hKey, hExpKey, dwBlobType, dwFlags, pbData, pdwDataLen); + + if (!key || !pdwDataLen) + CRYPT_ReturnLastError(ERROR_INVALID_PARAMETER); + + prov = key->pProvider; + return prov->pFuncs->pCPExportKey(prov->hPrivate, key->hPrivate, expkey ? expkey->hPrivate : 0, + dwBlobType, dwFlags, pbData, pdwDataLen); +} + +/****************************************************************************** + * CryptGenKey (ADVAPI32.@) + * + * Generates a random cryptographic session key or a pub/priv key pair. + * + * PARAMS + * hProv [I] Handle to a CSP. + * Algid [I] Algorithm to use to make key. + * dwFlags [I] Specifies type of key to make. + * phKey [I] Address of the handle to which the new key is copied. + * + * RETURNS + * Success: TRUE + * Failure: FALSE + */ +BOOL WINAPI CryptGenKey (HCRYPTPROV hProv, ALG_ID Algid, DWORD dwFlags, HCRYPTKEY *phKey) +{ + PCRYPTPROV prov = (PCRYPTPROV)hProv; + PCRYPTKEY key; + + TRACE("(0x%lx, %d, %08ld, %p)\n", hProv, Algid, dwFlags, phKey); + + if (!prov) + 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->pCPGenKey(prov->hPrivate, Algid, dwFlags, &key->hPrivate)) + { + *phKey = (HCRYPTKEY)key; + return TRUE; + } + + /* CSP error! */ + CRYPT_Free(key); + return FALSE; +} + +/****************************************************************************** + * CryptGetDefaultProviderA (ADVAPI32.@) + * + * Finds the default CSP of a certain provider type. + * + * PARAMS + * dwProvType [I] Provider type to look for. + * pdwReserved [I] Reserved for future use and must be NULL. + * dwFlags [I] CRYPT_MACHINE_DEFAULT/USER_DEFAULT + * pszProvName [O] Name of the default CSP. + * pcbProvName [I/O] Size of pszProvName + * + * RETURNS + * Success: TRUE + * Failure: FALSE + * + * NOTES + * If pszProvName is NULL, pcbProvName will hold the size of the buffer for + * memory allocation purposes on return. + */ +BOOL WINAPI CryptGetDefaultProviderA (DWORD dwProvType, DWORD *pdwReserved, + DWORD dwFlags, LPSTR pszProvName, DWORD *pcbProvName) +{ + HKEY hKey; + PSTR keyname; + DWORD result; + + if (pdwReserved || !pcbProvName) + CRYPT_ReturnLastError(ERROR_INVALID_PARAMETER); + if (dwFlags & ~(CRYPT_USER_DEFAULT | CRYPT_MACHINE_DEFAULT)) + CRYPT_ReturnLastError(NTE_BAD_FLAGS); + if (dwProvType > 999) + CRYPT_ReturnLastError(NTE_BAD_PROV_TYPE); + if ( !(keyname = CRYPT_GetTypeKeyName(dwProvType, dwFlags & CRYPT_USER_DEFAULT)) ) + CRYPT_ReturnLastError(ERROR_NOT_ENOUGH_MEMORY); + if (RegOpenKeyA((dwFlags & CRYPT_USER_DEFAULT) ? HKEY_CURRENT_USER : HKEY_LOCAL_MACHINE ,keyname, &hKey)) + { + CRYPT_Free(keyname); + CRYPT_ReturnLastError(NTE_PROV_TYPE_NOT_DEF); + } + CRYPT_Free(keyname); + + result = RegQueryValueExA(hKey, "Name", NULL, NULL, pszProvName, pcbProvName); + if (result) + { + if (result != ERROR_MORE_DATA) + SetLastError(NTE_PROV_TYPE_ENTRY_BAD); + else + SetLastError(result); + + return FALSE; + } + + RegCloseKey(hKey); + return TRUE; +} + +/****************************************************************************** + * CryptGetDefaultProviderW (ADVAPI32.@) + * + * see CryptGetDefaultProviderA + */ +BOOL WINAPI CryptGetDefaultProviderW (DWORD dwProvType, DWORD *pdwReserved, + DWORD dwFlags, LPWSTR pszProvName, DWORD *pcbProvName) +{ + PSTR str = NULL; + DWORD strlen; + BOOL ret = FALSE; + + TRACE("(%ld, %p, %08ld, %p, %p)\n", dwProvType, pdwReserved, dwFlags, pszProvName, pcbProvName); + + strlen = *pcbProvName / sizeof(WCHAR); + if ( pszProvName && !(str = CRYPT_Alloc(strlen)) ) + CRYPT_ReturnLastError(ERROR_NOT_ENOUGH_MEMORY); + ret = CryptGetDefaultProviderA(dwProvType, pdwReserved, dwFlags, str, &strlen); + if (str) + { + CRYPT_ANSIToUnicode(str, &pszProvName, *pcbProvName); + CRYPT_Free(str); + } + *pcbProvName = strlen * sizeof(WCHAR); + return ret; +} + +/****************************************************************************** + * CryptGetHashParam (ADVAPI32.@) + * + * Retrieves data that controls the operations of a hash object. + * + * PARAMS + * hHash [I] Handle of the hash object to question. + * dwParam [I] Query type. + * pbData [O] Buffer that receives the value data. + * pdwDataLen [I/O] Size of the pbData buffer. + * dwFlags [I] Reserved for future use and must be zero. + * + * RETURNS + * Success: TRUE + * Failure: FALSE + * + * NOTES + * If pbData is NULL, pdwDataLen will contain the length required. + */ +BOOL WINAPI CryptGetHashParam (HCRYPTHASH hHash, DWORD dwParam, BYTE *pbData, + DWORD *pdwDataLen, DWORD dwFlags) +{ + PCRYPTPROV prov; + PCRYPTHASH hash = (PCRYPTHASH)hHash; + + TRACE("(0x%lx, %ld, %p, %p, %08ld)\n", hHash, dwParam, pbData, pdwDataLen, dwFlags); + + if (!hash || !pdwDataLen) + CRYPT_ReturnLastError(ERROR_INVALID_PARAMETER); + + prov = hash->pProvider; + return prov->pFuncs->pCPGetHashParam(prov->hPrivate, hash->hPrivate, dwParam, + pbData, pdwDataLen, dwFlags); +} + +/****************************************************************************** + * CryptGetKeyParam (ADVAPI32.@) + * + * Retrieves data that controls the operations of a key. + * + * PARAMS + * hKey [I] Handle to they key in question. + * dwParam [I] Specifies query type. + * pbData [O] Sequence of bytes to receive data. + * pdwDataLen [I/O] Size of pbData. + * dwFlags [I] Reserved for future use and must be zero. + * + * RETURNS + * Success: TRUE + * Failure: FALSE + * + * NOTES + * If pbData is NULL, pdwDataLen is set to the needed length of the buffer. + */ +BOOL WINAPI CryptGetKeyParam (HCRYPTKEY hKey, DWORD dwParam, BYTE *pbData, + DWORD *pdwDataLen, DWORD dwFlags) +{ + PCRYPTPROV prov; + PCRYPTKEY key = (PCRYPTKEY)hKey; + + TRACE("(0x%lx, %ld, %p, %p, %08ld)\n", hKey, dwParam, pbData, pdwDataLen, dwFlags); + + if (!key || !pdwDataLen) + CRYPT_ReturnLastError(ERROR_INVALID_PARAMETER); + + prov = key->pProvider; + return prov->pFuncs->pCPGetKeyParam(prov->hPrivate, key->hPrivate, dwParam, + pbData, pdwDataLen, dwFlags); +} + +/****************************************************************************** + * CryptGetProvParam (ADVAPI32.@) + * + * Retrieves parameters that control the operations of a CSP. + * + * PARAMS + * hProv [I] Handle of the CSP in question. + * dwParam [I] Specifies query type. + * pbData [O] Buffer to receive the data. + * pdwDataLen [I/O] Size of pbData. + * dwFlags [I] see MSDN Docs. + * + * RETURNS + * Success: TRUE + * Failure: FALSE + * + * NOTES + * If pbData is NULL, pdwDataLen is set to the needed buffer length. + */ +BOOL WINAPI CryptGetProvParam (HCRYPTPROV hProv, DWORD dwParam, BYTE *pbData, + DWORD *pdwDataLen, DWORD dwFlags) +{ + PCRYPTPROV prov = (PCRYPTPROV)hProv; + + TRACE("(0x%lx, %ld, %p, %p, %08ld)\n", hProv, dwParam, pbData, pdwDataLen, dwFlags); + + return prov->pFuncs->pCPGetProvParam(prov->hPrivate, dwParam, pbData, pdwDataLen, dwFlags); +} + +/****************************************************************************** + * CryptGetUserKey (ADVAPI32.@) + * + * Gets a handle of one of a user's two public/private key pairs. + * + * PARAMS + * hProv [I] Handle of a CSP. + * dwKeySpec [I] Private key to use. + * phUserKey [O] Pointer to the handle of the retrieved keys. + * + * RETURNS + * Success: TRUE + * Failure: FALSE + */ +BOOL WINAPI CryptGetUserKey (HCRYPTPROV hProv, DWORD dwKeySpec, HCRYPTKEY *phUserKey) +{ + PCRYPTPROV prov = (PCRYPTPROV)hProv; + PCRYPTKEY key; + + TRACE("(0x%lx, %ld, %p)\n", hProv, dwKeySpec, phUserKey); + + if (!prov) + CRYPT_ReturnLastError(ERROR_INVALID_HANDLE); + if (!phUserKey) + CRYPT_ReturnLastError(ERROR_INVALID_PARAMETER); + if ( !(key = CRYPT_Alloc(sizeof(CRYPTKEY))) ) + CRYPT_ReturnLastError(ERROR_NOT_ENOUGH_MEMORY); + + key->pProvider = prov; + + if (prov->pFuncs->pCPGetUserKey(prov->hPrivate, dwKeySpec, &key->hPrivate)) + { + *phUserKey = (HCRYPTKEY)key; + return TRUE; + } + + /* CSP Error */ + CRYPT_Free(key); + *phUserKey = 0; + return FALSE; +} + +/****************************************************************************** + * CryptHashData (ADVAPI32.@) + * + * Adds data to a hash object. + * + * PARAMS + * hHash [I] Handle of the hash object. + * pbData [I] Buffer of data to be hashed. + * dwDataLen [I] Number of bytes to add. + * dwFlags [I] Can be CRYPT_USERDATA + * + * RETURNS + * Success: TRUE + * Failure: FALSE + */ +BOOL WINAPI CryptHashData (HCRYPTHASH hHash, BYTE *pbData, DWORD dwDataLen, DWORD dwFlags) +{ + PCRYPTHASH hash = (PCRYPTHASH)hHash; + PCRYPTPROV prov; + + TRACE("(0x%lx, %p, %ld, %08ld)\n", hHash, pbData, dwDataLen, dwFlags); + + if (!hash) + CRYPT_ReturnLastError(ERROR_INVALID_HANDLE); + if (!pbData || !dwDataLen) + CRYPT_ReturnLastError(ERROR_INVALID_PARAMETER); + + prov = hash->pProvider; + return prov->pFuncs->pCPHashData(prov->hPrivate, hash->hPrivate, pbData, dwDataLen, dwFlags); +} + +/****************************************************************************** + * CryptHashSessionKey (ADVAPI32.@) + * + * PARAMS + * hHash [I] Handle to the hash object. + * hKey [I] Handle to the key to be hashed. + * dwFlags [I] Can be CRYPT_LITTLE_ENDIAN. + * + * RETURNS + * Success: TRUE + * Failure: FALSE + */ +BOOL WINAPI CryptHashSessionKey (HCRYPTHASH hHash, HCRYPTKEY hKey, DWORD dwFlags) +{ + PCRYPTHASH hash = (PCRYPTHASH)hHash; + PCRYPTKEY key = (PCRYPTKEY)hKey; + PCRYPTPROV prov; + + TRACE("(0x%lx, 0x%lx, %08ld)\n", hHash, hKey, dwFlags); + + if (!hash || !key) + CRYPT_ReturnLastError(ERROR_INVALID_HANDLE); + + prov = hash->pProvider; + return prov->pFuncs->pCPHashSessionKey(prov->hPrivate, hash->hPrivate, key->hPrivate, dwFlags); +} + +/****************************************************************************** + * CryptImportKey (ADVAPI32.@) + * + * PARAMS + * hProv [I] Handle of a CSP. + * pbData [I] Contains the key to be imported. + * dwDataLen [I] Length of the key. + * hPubKey [I] Cryptographic key that decrypts pdData + * dwFlags [I] Used only with a public/private key pair. + * phKey [O] Imported key. + * + * RETURNS + * Success: TRUE + * Failure: FALSE + */ +BOOL WINAPI CryptImportKey (HCRYPTPROV hProv, BYTE *pbData, DWORD dwDataLen, + HCRYPTKEY hPubKey, DWORD dwFlags, HCRYPTKEY *phKey) +{ + PCRYPTPROV prov = (PCRYPTPROV)hProv; + PCRYPTKEY pubkey = (PCRYPTKEY)hPubKey, importkey; + + TRACE("(0x%lx, %p, %ld, 0x%lx, %08ld, %p)\n", hProv, pbData, dwDataLen, hPubKey, dwFlags, phKey); + + if (!prov || !pbData || !dwDataLen || !phKey) + CRYPT_ReturnLastError(ERROR_INVALID_PARAMETER); + + if ( !(importkey = CRYPT_Alloc(sizeof(CRYPTKEY))) ) + CRYPT_ReturnLastError(ERROR_NOT_ENOUGH_MEMORY); + + importkey->pProvider = prov; + if (prov->pFuncs->pCPImportKey(prov->hPrivate, pbData, dwDataLen, + pubkey ? pubkey->hPrivate : 0, dwFlags, &importkey->hPrivate)) + { + *phKey = (HCRYPTKEY)importkey; + return TRUE; + } + + CRYPT_Free(importkey); + return FALSE; +} + +/****************************************************************************** + * CryptSignHashA + * + * Note: Since the sDesciption (string) is supposed to be NULL and + * is only retained for compatibility no string conversions are required + * and only one implementation is required for both ANSI and Unicode. + * We still need to export both: + * + * CryptSignHashA (ADVAPI32.@) + * CryptSignHashW (ADVAPI32.@) + * + * Signs data. + * + * PARAMS + * hHash [I] Handle of the hash object to be signed. + * dwKeySpec [I] Private key to use. + * sDescription [I] Must be NULL. + * dwFlags [I] CRYPT_NOHASHOID/X931_FORMAT. + * pbSignature [O] Buffer of the signature data. + * pdwSigLen [I/O] Size of the pbSignature buffer. + * + * RETURNS + * Success: TRUE + * Failure: FALSE + */ +BOOL WINAPI CryptSignHashA (HCRYPTHASH hHash, DWORD dwKeySpec, LPCSTR sDescription, + DWORD dwFlags, BYTE *pbSignature, DWORD *pdwSigLen) +{ + PCRYPTHASH hash = (PCRYPTHASH)hHash; + PCRYPTPROV prov; + + TRACE("(0x%lx, %ld, %08ld, %p, %p)\n", hHash, dwKeySpec, dwFlags, pbSignature, pdwSigLen); + if (sDescription) + WARN("The sDescription parameter is not supported (and no longer used). Ignoring.\n"); + + if (!hash) + CRYPT_ReturnLastError(ERROR_INVALID_HANDLE); + if (!pdwSigLen) + CRYPT_ReturnLastError(ERROR_INVALID_PARAMETER); + + prov = hash->pProvider; + return prov->pFuncs->pCPSignHash(prov->hPrivate, hash->hPrivate, dwKeySpec, NULL, + dwFlags, pbSignature, pdwSigLen); +} + +/****************************************************************************** + * CryptSetHashParam (ADVAPI32.@) + * + * Customizes the operations of a hash object. + * + * PARAMS + * hHash [I] Handle of the hash object to set parameters. + * dwParam [I] HP_HMAC_INFO/HASHVAL. + * pbData [I] Value data buffer. + * dwFlags [I] Reserved for future use and must be zero. + * + * RETURNS + * Success: TRUE + * Failure: FALSE + */ +BOOL WINAPI CryptSetHashParam (HCRYPTHASH hHash, DWORD dwParam, BYTE *pbData, DWORD dwFlags) +{ + PCRYPTPROV prov; + PCRYPTHASH hash = (PCRYPTHASH)hHash; + + TRACE("(0x%lx, %ld, %p, %08ld)\n", hHash, dwParam, pbData, dwFlags); + + if (!hash || !pbData) + CRYPT_ReturnLastError(ERROR_INVALID_PARAMETER); + + prov = hash->pProvider; + return prov->pFuncs->pCPSetHashParam(prov->hPrivate, hash->hPrivate, + dwParam, pbData, dwFlags); +} + +/****************************************************************************** + * CryptSetKeyParam (ADVAPI32.@) + * + * Customizes a session key's operations. + * + * PARAMS + * hKey [I] Handle to the key to set values. + * dwParam [I] See MSDN Doc. + * pbData [I] Buffer of values to set. + * dwFlags [I] Only used when dwParam == KP_ALGID. + * + * RETURNS + * Success: TRUE + * Failure: FALSE + */ +BOOL WINAPI CryptSetKeyParam (HCRYPTKEY hKey, DWORD dwParam, BYTE *pbData, DWORD dwFlags) +{ + PCRYPTPROV prov; + PCRYPTKEY key = (PCRYPTKEY)hKey; + + TRACE("(0x%lx, %ld, %p, %08ld)\n", hKey, dwParam, pbData, dwFlags); + + if (!key || !pbData) + CRYPT_ReturnLastError(ERROR_INVALID_PARAMETER); + + prov = key->pProvider; + return prov->pFuncs->pCPSetKeyParam(prov->hPrivate, key->hPrivate, + dwParam, pbData, dwFlags); +} + +/****************************************************************************** + * CryptSetProviderA (ADVAPI32.@) + * + * Specifies the current user's default CSP. + * + * PARAMS + * pszProvName [I] Name of the new default CSP. + * dwProvType [I] Provider type of the CSP. + * + * RETURNS + * Success: TRUE + * Failure: FALSE + */ +BOOL WINAPI CryptSetProviderA (LPCSTR pszProvName, DWORD dwProvType) +{ + TRACE("(%s, %ld)\n", pszProvName, dwProvType); + return CryptSetProviderExA(pszProvName, dwProvType, NULL, CRYPT_USER_DEFAULT); +} + +/****************************************************************************** + * CryptSetProviderW (ADVAPI32.@) + * + * See CryptSetProviderA + */ +BOOL WINAPI CryptSetProviderW (LPCWSTR pszProvName, DWORD dwProvType) +{ + TRACE("(%s, %ld)\n", debugstr_w(pszProvName), dwProvType); + return CryptSetProviderExW(pszProvName, dwProvType, NULL, CRYPT_USER_DEFAULT); +} + +/****************************************************************************** + * CryptSetProviderExA (ADVAPI32.@) + * + * Specifies the default CSP. + * + * PARAMS + * pszProvName [I] Name of the new default CSP. + * dwProvType [I] Provider type of the CSP. + * pdwReserved [I] Reserved for future use and must be NULL. + * dwFlags [I] See MSDN Doc. + * + * RETURNS + * Success: TRUE + * Failure: FALSE + */ +BOOL WINAPI CryptSetProviderExA (LPCSTR pszProvName, DWORD dwProvType, DWORD *pdwReserved, DWORD dwFlags) +{ + HKEY hProvKey, hTypeKey; + PSTR keyname; + + TRACE("(%s, %ld, %p, %08ld)\n", pszProvName, dwProvType, pdwReserved, dwFlags); + + if (!pszProvName || pdwReserved) + CRYPT_ReturnLastError(ERROR_INVALID_PARAMETER); + if (dwProvType > MAXPROVTYPES) + CRYPT_ReturnLastError(NTE_BAD_PROV_TYPE); + if (dwFlags & ~(CRYPT_MACHINE_DEFAULT | CRYPT_USER_DEFAULT | CRYPT_DELETE_DEFAULT) + || dwFlags == CRYPT_DELETE_DEFAULT) + CRYPT_ReturnLastError(NTE_BAD_FLAGS); + + if (!(keyname = CRYPT_GetTypeKeyName(dwProvType, dwFlags & CRYPT_USER_DEFAULT))) + CRYPT_ReturnLastError(ERROR_NOT_ENOUGH_MEMORY); + if (RegOpenKeyA((dwFlags & CRYPT_USER_DEFAULT) ? HKEY_CURRENT_USER : HKEY_LOCAL_MACHINE, + keyname, &hTypeKey)) + { + CRYPT_Free(keyname); + CRYPT_ReturnLastError(NTE_BAD_PROVIDER); + } + CRYPT_Free(keyname); + + if (dwFlags & CRYPT_DELETE_DEFAULT) + { + RegDeleteValueA(hTypeKey, "Name"); + } + else + { + if (!(keyname = CRYPT_GetProvKeyName(pszProvName))) + { + RegCloseKey(hTypeKey); + CRYPT_ReturnLastError(ERROR_NOT_ENOUGH_MEMORY); + } + if (RegOpenKeyA((dwFlags & CRYPT_USER_DEFAULT) ? HKEY_CURRENT_USER : HKEY_LOCAL_MACHINE, + keyname, &hProvKey)) + { + CRYPT_Free(keyname); + RegCloseKey(hTypeKey); + CRYPT_ReturnLastError(NTE_BAD_PROVIDER); + } + CRYPT_Free(keyname); + + if (RegSetValueExA(hTypeKey, "Name", 0, REG_SZ, pszProvName, strlen(pszProvName) + 1)) + { + RegCloseKey(hTypeKey); + RegCloseKey(hProvKey); + return FALSE; + } + + RegCloseKey(hProvKey); + } + RegCloseKey(hTypeKey); + + return TRUE; +} + +/****************************************************************************** + * CryptSetProviderExW (ADVAPI32.@) + * + * See CryptSetProviderExA + */ +BOOL WINAPI CryptSetProviderExW (LPCWSTR pszProvName, DWORD dwProvType, DWORD *pdwReserved, DWORD dwFlags) +{ + BOOL ret = FALSE; + PSTR str = NULL; + + TRACE("(%s, %ld, %p, %08ld)\n", debugstr_w(pszProvName), dwProvType, pdwReserved, dwFlags); + + if (CRYPT_UnicodeToANSI(pszProvName, &str, -1)) + { + ret = CryptSetProviderExA(str, dwProvType, pdwReserved, dwFlags); + CRYPT_Free(str); + } + return ret; +} + +/****************************************************************************** + * CryptSetProvParam (ADVAPI32.@) + * + * Customizes the operations of a CSP. + * + * PARAMS + * hProv [I] Handle of a CSP. + * dwParam [I] See MSDN Doc. + * pbData [I] Buffer that contains a value to set as a parameter. + * dwFlags [I] if dwParam is PP_USE_HARDWARE_RNG, dwFlags must be zero. + * + * RETURNS + * Success: TRUE + * Failure: FALSE + */ +BOOL WINAPI CryptSetProvParam (HCRYPTPROV hProv, DWORD dwParam, BYTE *pbData, DWORD dwFlags) +{ + PCRYPTPROV prov = (PCRYPTPROV)hProv; + + TRACE("(0x%lx, %ld, %p, %08ld)\n", hProv, dwParam, pbData, dwFlags); + + if (!prov) + CRYPT_ReturnLastError(ERROR_INVALID_HANDLE); + if (dwFlags & PP_USE_HARDWARE_RNG) + { + FIXME("PP_USE_HARDWARE_RNG: What do I do with this?\n"); + FIXME("\tLetting the CSP decide.\n"); + } + if (dwFlags & PP_CLIENT_HWND) + { + /* FIXME: Should verify the parameter */ + if (pbData /* && IsWindow((HWND)pbData) */) + { + crypt_hWindow = (HWND)(pbData); + return TRUE; + } else { + SetLastError(ERROR_INVALID_PARAMETER); + return FALSE; + } + } + /* All other flags go to the CSP */ + return prov->pFuncs->pCPSetProvParam(prov->hPrivate, dwParam, pbData, dwFlags); +} + +/****************************************************************************** + * CryptVerifySignatureA + * + * Note: Since the sDesciption (string) is supposed to be NULL and + * is only retained for compatibility no string conversions are required + * and only one implementation is required for both ANSI and Unicode. + * We still need to export both: + * + * CryptVerifySignatureA (ADVAPI32.@) + * CryptVerifySignatureW (ADVAPI32.@) + * + * Verifies the signature of a hash object. + * + * PARAMS + * hHash [I] Handle of the hash object to verify. + * pbSignature [I] Signature data to verify. + * dwSigLen [I] Size of pbSignature. + * hPubKey [I] Handle to the public key to authenticate signature. + * sDescription [I] Must be set to NULL. + * dwFlags [I] See MSDN doc. + * + * RETURNS + * Success: TRUE + * Failure: FALSE + */ +BOOL WINAPI CryptVerifySignatureA (HCRYPTHASH hHash, BYTE *pbSignature, DWORD dwSigLen, + HCRYPTKEY hPubKey, LPCSTR sDescription, DWORD dwFlags) +{ + PCRYPTHASH hash = (PCRYPTHASH)hHash; + PCRYPTKEY key = (PCRYPTKEY)hPubKey; + PCRYPTPROV prov; + + TRACE("(0x%lx, %p, %ld, 0x%lx, %08ld)\n", hHash, pbSignature, + dwSigLen, hPubKey, dwFlags); + if (sDescription) + WARN("The sDescription parameter is not supported (and no longer used). Ignoring.\n"); + + if (!hash || !key) + CRYPT_ReturnLastError(ERROR_INVALID_HANDLE); + if (!pbSignature || !dwSigLen) + CRYPT_ReturnLastError(ERROR_INVALID_PARAMETER); + + prov = hash->pProvider; + return prov->pFuncs->pCPVerifySignature(prov->hPrivate, hash->hPrivate, pbSignature, dwSigLen, + key->hPrivate, NULL, dwFlags); +} + + +/* + These functions have nearly identical prototypes to CryptProtectMemory and CryptUnprotectMemory, + in crypt32.dll. + */ + +/****************************************************************************** + * SystemFunction040 (ADVAPI32.@) + * + * PARAMS: + * memory : pointer to memory to encrypt + * length : length of region to encrypt, in bytes. must be multiple of RTL_ENCRYPT_MEMORY_SIZE + * flags : RTL_ENCRYPT_OPTION_SAME_PROCESS | RTL_ENCRYPT_OPTION_CROSS_PROCESS, | RTL_ENCRYPT_OPTION_SAME_LOGON + * control whether other processes are able to decrypt the memory. The same value must be given + * when decrypting the memory. + */ +NTSTATUS WINAPI SystemFunction040(PVOID memory, ULONG length, ULONG flags) /* RtlEncryptMemory */ +{ + FIXME("(%p, %lx, %lx): stub [RtlEncryptMemory]\n", memory, length, flags); + return STATUS_SUCCESS; +} + +/****************************************************************************** + * SystemFunction041 (ADVAPI32.@) + * + * PARAMS: + * memory : pointer to memory to decrypt + * length : length of region to decrypt, in bytes. must be multiple of RTL_ENCRYPT_MEMORY_SIZE + * flags : RTL_ENCRYPT_OPTION_SAME_PROCESS | RTL_ENCRYPT_OPTION_CROSS_PROCESS, | RTL_ENCRYPT_OPTION_SAME_LOGON + * control whether other processes are able to decrypt the memory. The same value must be given + * when encrypting the memory. + */ +NTSTATUS WINAPI SystemFunction041(PVOID memory, ULONG length, ULONG flags) /* RtlDecryptMemory */ +{ + FIXME("(%p, %lx, %lx): stub [RtlDecryptMemory]\n", memory, length, flags); + return STATUS_SUCCESS; +} diff --git a/reactos/lib/advapi32/crypt/crypt.h b/reactos/lib/advapi32/crypt/crypt.h new file mode 100644 index 00000000000..4a56363b519 --- /dev/null +++ b/reactos/lib/advapi32/crypt/crypt.h @@ -0,0 +1,86 @@ +/* + * Driver routines + * + * 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 + */ + +#ifndef __WINE_CRYPT_H +#define __WINE_CRYPT_H + +#include + +#include "windef.h" +#include "winbase.h" +#include "wincrypt.h" + +typedef struct tagPROVFUNCS +{ + BOOL (WINAPI *pCPAcquireContext)(HCRYPTPROV *phProv, LPSTR pszContainer, DWORD dwFlags, PVTableProvStruc pVTable); + BOOL (WINAPI *pCPCreateHash)(HCRYPTPROV hProv, ALG_ID Algid, HCRYPTKEY hKey, DWORD dwFlags, HCRYPTHASH *phHash); + BOOL (WINAPI *pCPDecrypt)(HCRYPTPROV hProv, HCRYPTKEY hKey, HCRYPTHASH hHash, BOOL Final, DWORD dwFlags, BYTE *pbData, DWORD *pdwDataLen); + BOOL (WINAPI *pCPDeriveKey)(HCRYPTPROV hProv, ALG_ID Algid, HCRYPTHASH hBaseData, DWORD dwFlags, HCRYPTKEY *phKey); + BOOL (WINAPI *pCPDestroyHash)(HCRYPTPROV hProv, HCRYPTHASH hHash); + BOOL (WINAPI *pCPDestroyKey)(HCRYPTPROV hProv, HCRYPTKEY hKey); + BOOL (WINAPI *pCPDuplicateHash)(HCRYPTPROV hUID, HCRYPTHASH hHash, DWORD *pdwReserved, DWORD dwFlags, HCRYPTHASH *phHash); + BOOL (WINAPI *pCPDuplicateKey)(HCRYPTPROV hUID, HCRYPTKEY hKey, DWORD *pdwReserved, DWORD dwFlags, HCRYPTKEY *phKey); + BOOL (WINAPI *pCPEncrypt)(HCRYPTPROV hProv, HCRYPTKEY hKey, HCRYPTHASH hHash, BOOL Final, DWORD dwFlags, BYTE *pbData, DWORD *pdwDataLen, DWORD dwBufLen); + BOOL (WINAPI *pCPExportKey)(HCRYPTPROV hProv, HCRYPTKEY hKey, HCRYPTKEY hPubKey, DWORD dwBlobType, DWORD dwFlags, BYTE *pbData, DWORD *pdwDataLen); + BOOL (WINAPI *pCPGenKey)(HCRYPTPROV hProv, ALG_ID Algid, DWORD dwFlags, HCRYPTKEY *phKey); + BOOL (WINAPI *pCPGenRandom)(HCRYPTPROV hProv, DWORD dwLen, BYTE *pbBuffer); + BOOL (WINAPI *pCPGetHashParam)(HCRYPTPROV hProv, HCRYPTHASH hHash, DWORD dwParam, BYTE *pbData, DWORD *pdwDataLen, DWORD dwFlags); + BOOL (WINAPI *pCPGetKeyParam)(HCRYPTPROV hProv, HCRYPTKEY hKey, DWORD dwParam, BYTE *pbData, DWORD *pdwDataLen, DWORD dwFlags); + BOOL (WINAPI *pCPGetProvParam)(HCRYPTPROV hProv, DWORD dwParam, BYTE *pbData, DWORD *pdwDataLen, DWORD dwFlags); + BOOL (WINAPI *pCPGetUserKey)(HCRYPTPROV hProv, DWORD dwKeySpec, HCRYPTKEY *phUserKey); + BOOL (WINAPI *pCPHashData)(HCRYPTPROV hProv, HCRYPTHASH hHash, CONST BYTE *pbData, DWORD dwDataLen, DWORD dwFlags); + BOOL (WINAPI *pCPHashSessionKey)(HCRYPTPROV hProv, HCRYPTHASH hHash, HCRYPTKEY hKey, DWORD dwFlags); + BOOL (WINAPI *pCPImportKey)(HCRYPTPROV hProv, CONST BYTE *pbData, DWORD dwDataLen, HCRYPTKEY hPubKey, DWORD dwFlags, HCRYPTKEY *phKey); + BOOL (WINAPI *pCPReleaseContext)(HCRYPTPROV hProv, DWORD dwFlags); + BOOL (WINAPI *pCPSetHashParam)(HCRYPTPROV hProv, HCRYPTHASH hHash, DWORD dwParam, BYTE *pbData, DWORD dwFlags); + BOOL (WINAPI *pCPSetKeyParam)(HCRYPTPROV hProv, HCRYPTKEY hKey, DWORD dwParam, BYTE *pbData, DWORD dwFlags); + BOOL (WINAPI *pCPSetProvParam)(HCRYPTPROV hProv, DWORD dwParam, BYTE *pbData, DWORD dwFlags); + BOOL (WINAPI *pCPSignHash)(HCRYPTPROV hProv, HCRYPTHASH hHash, DWORD dwKeySpec, LPCWSTR sDescription, DWORD dwFlags, BYTE *pbSignature, DWORD *pdwSigLen); + BOOL (WINAPI *pCPVerifySignature)(HCRYPTPROV hProv, HCRYPTHASH hHash, CONST BYTE *pbSignature, DWORD dwSigLen, HCRYPTKEY hPubKey, LPCWSTR sDescription, DWORD dwFlags); +} PROVFUNCS, *PPROVFUNCS; + +typedef struct tagCRYPTPROV +{ + UINT refcount; + HMODULE hModule; + PPROVFUNCS pFuncs; + HCRYPTPROV hPrivate; /*CSP's handle - Should not be given to application under any circumstances!*/ + PVTableProvStruc pVTable; +} CRYPTPROV, *PCRYPTPROV; + +typedef struct tagCRYPTKEY +{ + PCRYPTPROV pProvider; + HCRYPTKEY hPrivate; /*CSP's handle - Should not be given to application under any circumstances!*/ +} CRYPTKEY, *PCRYPTKEY; + +typedef struct tagCRYPTHASH +{ + PCRYPTPROV pProvider; + HCRYPTHASH hPrivate; /*CSP's handle - Should not be given to application under any circumstances!*/ +} CRYPTHASH, *PCRYPTHASH; + +#define MAXPROVTYPES 999 + +extern unsigned char *CRYPT_DESkey8to7( unsigned char *dst, const unsigned char *key ); +extern unsigned char *CRYPT_DEShash( unsigned char *dst, const unsigned char *key, + const unsigned char *src ); + +#endif /* __WINE_CRYPT_H_ */ diff --git a/reactos/lib/advapi32/crypt/crypt_des.c b/reactos/lib/advapi32/crypt/crypt_des.c new file mode 100644 index 00000000000..4b527dddf27 --- /dev/null +++ b/reactos/lib/advapi32/crypt/crypt_des.c @@ -0,0 +1,290 @@ +/* + * Copyright 2004 Hans Leidekker + * + * Based on DES.c from libcifs + * + * Copyright (C) 2003, 2004 by Christopher R. Hertel + * + * 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 + */ + +#include "windef.h" +#include "crypt.h" + +static const unsigned char InitialPermuteMap[64] = +{ + 57, 49, 41, 33, 25, 17, 9, 1, + 59, 51, 43, 35, 27, 19, 11, 3, + 61, 53, 45, 37, 29, 21, 13, 5, + 63, 55, 47, 39, 31, 23, 15, 7, + 56, 48, 40, 32, 24, 16, 8, 0, + 58, 50, 42, 34, 26, 18, 10, 2, + 60, 52, 44, 36, 28, 20, 12, 4, + 62, 54, 46, 38, 30, 22, 14, 6 + }; + +static const unsigned char KeyPermuteMap[56] = +{ + 49, 42, 35, 28, 21, 14, 7, 0, + 50, 43, 36, 29, 22, 15, 8, 1, + 51, 44, 37, 30, 23, 16, 9, 2, + 52, 45, 38, 31, 55, 48, 41, 34, + 27, 20, 13, 6, 54, 47, 40, 33, + 26, 19, 12, 5, 53, 46, 39, 32, + 25, 18, 11, 4, 24, 17, 10, 3, +}; + +static const unsigned char KeyRotation[16] = + { 1, 1, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 1 }; + +static const unsigned char KeyCompression[48] = +{ + 13, 16, 10, 23, 0, 4, 2, 27, + 14, 5, 20, 9, 22, 18, 11, 3, + 25, 7, 15, 6, 26, 19, 12, 1, + 40, 51, 30, 36, 46, 54, 29, 39, + 50, 44, 32, 47, 43, 48, 38, 55, + 33, 52, 45, 41, 49, 35, 28, 31 +}; + +static const unsigned char DataExpansion[48] = +{ + 31, 0, 1, 2, 3, 4, 3, 4, + 5, 6, 7, 8, 7, 8, 9, 10, + 11, 12, 11, 12, 13, 14, 15, 16, + 15, 16, 17, 18, 19, 20, 19, 20, + 21, 22, 23, 24, 23, 24, 25, 26, + 27, 28, 27, 28, 29, 30, 31, 0 +}; + +static const unsigned char SBox[8][64] = +{ + { /* S0 */ + 14, 0, 4, 15, 13, 7, 1, 4, 2, 14, 15, 2, 11, 13, 8, 1, + 3, 10, 10, 6, 6, 12, 12, 11, 5, 9, 9, 5, 0, 3, 7, 8, + 4, 15, 1, 12, 14, 8, 8, 2, 13, 4, 6, 9, 2, 1, 11, 7, + 15, 5, 12, 11, 9, 3, 7, 14, 3, 10, 10, 0, 5, 6, 0, 13 + }, + { /* S1 */ + 15, 3, 1, 13, 8, 4, 14, 7, 6, 15, 11, 2, 3, 8, 4, 14, + 9, 12, 7, 0, 2, 1, 13, 10, 12, 6, 0, 9, 5, 11, 10, 5, + 0, 13, 14, 8, 7, 10, 11, 1, 10, 3, 4, 15, 13, 4, 1, 2, + 5, 11, 8, 6, 12, 7, 6, 12, 9, 0, 3, 5, 2, 14, 15, 9 + }, + { /* S2 */ + 10, 13, 0, 7, 9, 0, 14, 9, 6, 3, 3, 4, 15, 6, 5, 10, + 1, 2, 13, 8, 12, 5, 7, 14, 11, 12, 4, 11, 2, 15, 8, 1, + 13, 1, 6, 10, 4, 13, 9, 0, 8, 6, 15, 9, 3, 8, 0, 7, + 11, 4, 1, 15, 2, 14, 12, 3, 5, 11, 10, 5, 14, 2, 7, 12 + }, + { /* S3 */ + 7, 13, 13, 8, 14, 11, 3, 5, 0, 6, 6, 15, 9, 0, 10, 3, + 1, 4, 2, 7, 8, 2, 5, 12, 11, 1, 12, 10, 4, 14, 15, 9, + 10, 3, 6, 15, 9, 0, 0, 6, 12, 10, 11, 1, 7, 13, 13, 8, + 15, 9, 1, 4, 3, 5, 14, 11, 5, 12, 2, 7, 8, 2, 4, 14 + }, + { /* S4 */ + 2, 14, 12, 11, 4, 2, 1, 12, 7, 4, 10, 7, 11, 13, 6, 1, + 8, 5, 5, 0, 3, 15, 15, 10, 13, 3, 0, 9, 14, 8, 9, 6, + 4, 11, 2, 8, 1, 12, 11, 7, 10, 1, 13, 14, 7, 2, 8, 13, + 15, 6, 9, 15, 12, 0, 5, 9, 6, 10, 3, 4, 0, 5, 14, 3 + }, + { /* S5 */ + 12, 10, 1, 15, 10, 4, 15, 2, 9, 7, 2, 12, 6, 9, 8, 5, + 0, 6, 13, 1, 3, 13, 4, 14, 14, 0, 7, 11, 5, 3, 11, 8, + 9, 4, 14, 3, 15, 2, 5, 12, 2, 9, 8, 5, 12, 15, 3, 10, + 7, 11, 0, 14, 4, 1, 10, 7, 1, 6, 13, 0, 11, 8, 6, 13 + }, + { /* S6 */ + 4, 13, 11, 0, 2, 11, 14, 7, 15, 4, 0, 9, 8, 1, 13, 10, + 3, 14, 12, 3, 9, 5, 7, 12, 5, 2, 10, 15, 6, 8, 1, 6, + 1, 6, 4, 11, 11, 13, 13, 8, 12, 1, 3, 4, 7, 10, 14, 7, + 10, 9, 15, 5, 6, 0, 8, 15, 0, 14, 5, 2, 9, 3, 2, 12 + }, + { /* S7 */ + 13, 1, 2, 15, 8, 13, 4, 8, 6, 10, 15, 3, 11, 7, 1, 4, + 10, 12, 9, 5, 3, 6, 14, 11, 5, 0, 0, 14, 12, 9, 7, 2, + 7, 2, 11, 1, 4, 14, 1, 7, 9, 4, 12, 10, 14, 8, 2, 13, + 0, 15, 6, 12, 10, 9, 13, 0, 15, 3, 3, 5, 5, 6, 8, 11 + } +}; + +static const unsigned char PBox[32] = +{ + 15, 6, 19, 20, 28, 11, 27, 16, + 0, 14, 22, 25, 4, 17, 30, 9, + 1, 7, 23, 13, 31, 26, 2, 8, + 18, 12, 29, 5, 21, 10, 3, 24 +}; + +static const unsigned char FinalPermuteMap[64] = +{ + 7, 39, 15, 47, 23, 55, 31, 63, + 6, 38, 14, 46, 22, 54, 30, 62, + 5, 37, 13, 45, 21, 53, 29, 61, + 4, 36, 12, 44, 20, 52, 28, 60, + 3, 35, 11, 43, 19, 51, 27, 59, + 2, 34, 10, 42, 18, 50, 26, 58, + 1, 33, 9, 41, 17, 49, 25, 57, + 0, 32, 8, 40, 16, 48, 24, 56 +}; + +#define CLRBIT( STR, IDX ) ( (STR)[(IDX)/8] &= ~(0x01 << (7 - ((IDX)%8))) ) +#define SETBIT( STR, IDX ) ( (STR)[(IDX)/8] |= (0x01 << (7 - ((IDX)%8))) ) +#define GETBIT( STR, IDX ) (( ((STR)[(IDX)/8]) >> (7 - ((IDX)%8)) ) & 0x01) + +static void Permute( unsigned char *dst, const unsigned char *src, const unsigned char *map, const int mapsize ) +{ + int bitcount, i; + + for (i = 0; i < mapsize; i++) + dst[i] = 0; + + bitcount = mapsize * 8; + + for (i = 0; i < bitcount; i++) + { + if (GETBIT( src, map[i] )) + SETBIT( dst, i ); + } +} + +static void KeyShift( unsigned char *key, const int numbits ) +{ + int i; + unsigned char keep = key[0]; + + for (i = 0; i < numbits; i++) + { + int j; + + for (j = 0; j < 7; j++) + { + if (j && (key[j] & 0x80)) + key[j-1] |= 0x01; + key[j] <<= 1; + } + + if (GETBIT( key, 27 )) + { + CLRBIT( key, 27 ); + SETBIT( key, 55 ); + } + + if (keep & 0x80) + SETBIT( key, 27 ); + + keep <<= 1; + } +} + +static void sbox( unsigned char *dst, const unsigned char *src ) +{ + int i; + + for (i = 0; i < 4; i++) + dst[i] = 0; + + for (i = 0; i < 8; i++) + { + int j, Snum, bitnum; + + for (Snum = j = 0, bitnum = (i * 6); j < 6; j++, bitnum++) + { + Snum <<= 1; + Snum |= GETBIT( src, bitnum ); + } + + if (0 == (i%2)) + dst[i/2] |= ((SBox[i][Snum]) << 4); + else + dst[i/2] |= SBox[i][Snum]; + } +} + +static void xor( unsigned char *dst, const unsigned char *a, const unsigned char *b, const int count ) +{ + int i; + + for (i = 0; i < count; i++) + dst[i] = a[i] ^ b[i]; +} + +unsigned char *CRYPT_DESkey8to7( unsigned char *dst, const unsigned char *key ) +{ + int i; + unsigned char tmp[7]; + static const unsigned char map8to7[56] = + { + 0, 1, 2, 3, 4, 5, 6, + 8, 9, 10, 11, 12, 13, 14, + 16, 17, 18, 19, 20, 21, 22, + 24, 25, 26, 27, 28, 29, 30, + 32, 33, 34, 35, 36, 37, 38, + 40, 41, 42, 43, 44, 45, 46, + 48, 49, 50, 51, 52, 53, 54, + 56, 57, 58, 59, 60, 61, 62 + }; + + if ((dst == NULL) || (key == NULL)) + return NULL; + + Permute( tmp, key, map8to7, 7 ); + + for (i = 0; i < 7; i++) + dst[i] = tmp[i]; + + return dst; +} + +unsigned char *CRYPT_DEShash( unsigned char *dst, const unsigned char *key, const unsigned char *src ) +{ + int i; + unsigned char K[7]; + unsigned char D[8]; + + Permute( K, key, KeyPermuteMap, 7 ); + Permute( D, src, InitialPermuteMap, 8 ); + + for (i = 0; i < 16; i++) + { + int j; + unsigned char *L = D; + unsigned char *R = &(D[4]); + unsigned char Rexp[6]; + unsigned char Rn[4]; + unsigned char SubK[6]; + + KeyShift( K, KeyRotation[i] ); + Permute( SubK, K, KeyCompression, 6 ); + + Permute( Rexp, R, DataExpansion, 6 ); + xor( Rexp, Rexp, SubK, 6 ); + + sbox( Rn, Rexp ); + Permute( Rexp, Rn, PBox, 4 ); + xor( Rn, L, Rexp, 4 ); + + for (j = 0; j < 4; j++) + { + L[j] = R[j]; + R[j] = Rn[j]; + } + } + + Permute( dst, D, FinalPermuteMap, 8 ); + + return dst; +} diff --git a/reactos/lib/advapi32/crypt/crypt_lmhash.c b/reactos/lib/advapi32/crypt/crypt_lmhash.c new file mode 100644 index 00000000000..42367689667 --- /dev/null +++ b/reactos/lib/advapi32/crypt/crypt_lmhash.c @@ -0,0 +1,60 @@ +/* + * Copyright 2004 Hans Leidekker + * + * Based on LMHash.c from libcifs + * + * Copyright (C) 2004 by Christopher R. Hertel + * + * 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 + */ + +#include + +#include "windef.h" +#include "winbase.h" +#include "winreg.h" + +typedef LONG (CALLBACK *PVECTORED_EXCEPTION_HANDLER)( + struct _EXCEPTION_POINTERS *ExceptionInfo + ); + +#include "wine/winternl.h" +#include "wine/ntstatus.h" + +#include "crypt.h" + +static const unsigned char CRYPT_LMhash_Magic[8] = + { 'K', 'G', 'S', '!', '@', '#', '$', '%' }; + +static void CRYPT_LMhash( unsigned char *dst, const unsigned char *pwd, const int len ) +{ + int i, max = 14; + unsigned char tmp_pwd[14] = { 0,0,0,0,0,0,0,0,0,0,0,0,0,0 }; + + max = len > max ? max : len; + + for (i = 0; i < max; i++) + tmp_pwd[i] = pwd[i]; + + CRYPT_DEShash( dst, tmp_pwd, CRYPT_LMhash_Magic ); + CRYPT_DEShash( &dst[8], &tmp_pwd[7], CRYPT_LMhash_Magic ); +} + +NTSTATUS WINAPI SystemFunction006( LPCSTR password, LPSTR hash ) +{ + CRYPT_LMhash( hash, password, strlen(password) ); + + return STATUS_SUCCESS; +} diff --git a/reactos/lib/advapi32/crypt/crypt_md4.c b/reactos/lib/advapi32/crypt/crypt_md4.c new file mode 100644 index 00000000000..4c3f9bb92db --- /dev/null +++ b/reactos/lib/advapi32/crypt/crypt_md4.c @@ -0,0 +1,270 @@ +/* + * Copyright (C) 2001 Nikos Mavroyanopoulos + * Copyright (C) 2004 Hans Leidekker + * + * 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 + */ + +/* + * This code implements the MD4 message-digest algorithm. + * It is based on code in the public domain written by Colin + * Plumb in 1993. The algorithm is due to Ron Rivest. + * + * Equivalent code is available from RSA Data Security, Inc. + * This code has been tested against that, and is equivalent, + * except that you don't need to include two pages of legalese + * with every copy. + * + * To compute the message digest of a chunk of bytes, declare an + * MD4_CTX structure, pass it to MD4Init, call MD4Update as + * needed on buffers full of bytes, and then call MD4Final, which + * will fill a supplied 16-byte array with the digest. + */ + +#include + +#include "windef.h" +#include "winbase.h" + +typedef struct +{ + unsigned int buf[4]; + unsigned int i[2]; + unsigned char in[64]; + unsigned char digest[16]; +} MD4_CTX; + +static void MD4Transform( unsigned int buf[4], unsigned int const in[16] ); + +/* + * Note: this code is harmless on little-endian machines. + */ +static void byteReverse( unsigned char *buf, unsigned longs ) +{ + unsigned int t; + + do { + t = (unsigned int)((unsigned)buf[3] << 8 | buf[2]) << 16 | + ((unsigned)buf[1] << 8 | buf[0]); + *(unsigned int *)buf = t; + buf += 4; + } while (--longs); +} + +/* + * Start MD4 accumulation. Set bit count to 0 and buffer to mysterious + * initialization constants. + */ +VOID WINAPI MD4Init( MD4_CTX *ctx ) +{ + ctx->buf[0] = 0x67452301; + ctx->buf[1] = 0xefcdab89; + ctx->buf[2] = 0x98badcfe; + ctx->buf[3] = 0x10325476; + + ctx->i[0] = ctx->i[1] = 0; +} + +/* + * Update context to reflect the concatenation of another buffer full + * of bytes. + */ +VOID WINAPI MD4Update( MD4_CTX *ctx, const unsigned char *buf, unsigned int len ) +{ + register unsigned int t; + + /* Update bitcount */ + t = ctx->i[0]; + + if ((ctx->i[0] = t + ((unsigned int)len << 3)) < t) + ctx->i[1]++; /* Carry from low to high */ + + ctx->i[1] += len >> 29; + t = (t >> 3) & 0x3f; + + /* Handle any leading odd-sized chunks */ + if (t) + { + unsigned char *p = (unsigned char *)ctx->in + t; + t = 64 - t; + + if (len < t) + { + memcpy( p, buf, len ); + return; + } + + memcpy( p, buf, t ); + byteReverse( ctx->in, 16 ); + + MD4Transform( ctx->buf, (unsigned int *)ctx->in ); + + buf += t; + len -= t; + } + + /* Process data in 64-byte chunks */ + while (len >= 64) + { + memcpy( ctx->in, buf, 64 ); + byteReverse( ctx->in, 16 ); + + MD4Transform( ctx->buf, (unsigned int *)ctx->in ); + + buf += 64; + len -= 64; + } + + /* Handle any remaining bytes of data. */ + memcpy( ctx->in, buf, len ); +} + +/* + * Final wrapup - pad to 64-byte boundary with the bit pattern + * 1 0* (64-bit count of bits processed, MSB-first) + */ +VOID WINAPI MD4Final( MD4_CTX *ctx ) +{ + unsigned int count; + unsigned char *p; + + /* Compute number of bytes mod 64 */ + count = (ctx->i[0] >> 3) & 0x3F; + + /* Set the first char of padding to 0x80. This is safe since there is + always at least one byte free */ + p = ctx->in + count; + *p++ = 0x80; + + /* Bytes of padding needed to make 64 bytes */ + count = 64 - 1 - count; + + /* Pad out to 56 mod 64 */ + if (count < 8) + { + /* Two lots of padding: Pad the first block to 64 bytes */ + memset( p, 0, count ); + byteReverse( ctx->in, 16 ); + MD4Transform( ctx->buf, (unsigned int *)ctx->in ); + + /* Now fill the next block with 56 bytes */ + memset( ctx->in, 0, 56 ); + } + else + { + /* Pad block to 56 bytes */ + memset( p, 0, count - 8 ); + } + + byteReverse( ctx->in, 14 ); + + /* Append length in bits and transform */ + ((unsigned int *)ctx->in)[14] = ctx->i[0]; + ((unsigned int *)ctx->in)[15] = ctx->i[1]; + + MD4Transform( ctx->buf, (unsigned int *)ctx->in ); + byteReverse( (unsigned char *)ctx->buf, 4 ); + memcpy( ctx->digest, ctx->buf, 16 ); +} + +/* The three core functions */ + +#define rotl32(x,n) (((x) << ((unsigned int)(n))) | ((x) >> (32 - (unsigned int)(n)))) + +#define F( x, y, z ) (((x) & (y)) | ((~x) & (z))) +#define G( x, y, z ) (((x) & (y)) | ((x) & (z)) | ((y) & (z))) +#define H( x, y, z ) ((x) ^ (y) ^ (z)) + +#define FF( a, b, c, d, x, s ) { \ + (a) += F( (b), (c), (d) ) + (x); \ + (a) = rotl32( (a), (s) ); \ + } +#define GG( a, b, c, d, x, s ) { \ + (a) += G( (b), (c), (d) ) + (x) + (unsigned int)0x5a827999; \ + (a) = rotl32( (a), (s) ); \ + } +#define HH( a, b, c, d, x, s ) { \ + (a) += H( (b), (c), (d) ) + (x) + (unsigned int)0x6ed9eba1; \ + (a) = rotl32( (a), (s) ); \ + } + +/* + * The core of the MD4 algorithm + */ +static void MD4Transform( unsigned int buf[4], const unsigned int in[16] ) +{ + register unsigned int a, b, c, d; + + a = buf[0]; + b = buf[1]; + c = buf[2]; + d = buf[3]; + + FF( a, b, c, d, in[0], 3 ); + FF( d, a, b, c, in[1], 7 ); + FF( c, d, a, b, in[2], 11 ); + FF( b, c, d, a, in[3], 19 ); + FF( a, b, c, d, in[4], 3 ); + FF( d, a, b, c, in[5], 7 ); + FF( c, d, a, b, in[6], 11 ); + FF( b, c, d, a, in[7], 19 ); + FF( a, b, c, d, in[8], 3 ); + FF( d, a, b, c, in[9], 7 ); + FF( c, d, a, b, in[10], 11 ); + FF( b, c, d, a, in[11], 19 ); + FF( a, b, c, d, in[12], 3 ); + FF( d, a, b, c, in[13], 7 ); + FF( c, d, a, b, in[14], 11 ); + FF( b, c, d, a, in[15], 19 ); + + GG( a, b, c, d, in[0], 3 ); + GG( d, a, b, c, in[4], 5 ); + GG( c, d, a, b, in[8], 9 ); + GG( b, c, d, a, in[12], 13 ); + GG( a, b, c, d, in[1], 3 ); + GG( d, a, b, c, in[5], 5 ); + GG( c, d, a, b, in[9], 9 ); + GG( b, c, d, a, in[13], 13 ); + GG( a, b, c, d, in[2], 3 ); + GG( d, a, b, c, in[6], 5 ); + GG( c, d, a, b, in[10], 9 ); + GG( b, c, d, a, in[14], 13 ); + GG( a, b, c, d, in[3], 3 ); + GG( d, a, b, c, in[7], 5 ); + GG( c, d, a, b, in[11], 9 ); + GG( b, c, d, a, in[15], 13 ); + + HH( a, b, c, d, in[0], 3 ); + HH( d, a, b, c, in[8], 9 ); + HH( c, d, a, b, in[4], 11 ); + HH( b, c, d, a, in[12], 15 ); + HH( a, b, c, d, in[2], 3 ); + HH( d, a, b, c, in[10], 9 ); + HH( c, d, a, b, in[6], 11 ); + HH( b, c, d, a, in[14], 15 ); + HH( a, b, c, d, in[1], 3 ); + HH( d, a, b, c, in[9], 9 ); + HH( c, d, a, b, in[5], 11 ); + HH( b, c, d, a, in[13], 15 ); + HH( a, b, c, d, in[3], 3 ); + HH( d, a, b, c, in[11], 9 ); + HH( c, d, a, b, in[7], 11 ); + HH( b, c, d, a, in[15], 15 ); + + buf[0] += a; + buf[1] += b; + buf[2] += c; + buf[3] += d; +} diff --git a/reactos/lib/advapi32/crypt/crypt_md5.c b/reactos/lib/advapi32/crypt/crypt_md5.c new file mode 100644 index 00000000000..96ff048967d --- /dev/null +++ b/reactos/lib/advapi32/crypt/crypt_md5.c @@ -0,0 +1,280 @@ +/* + * Copyright (C) 2001 Nikos Mavroyanopoulos + * Copyright (C) 2004 Hans Leidekker + * + * 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 + */ + +/* + * This code implements the MD5 message-digest algorithm. + * It is based on code in the public domain written by Colin + * Plumb in 1993. The algorithm is due to Ron Rivest. + * + * Equivalent code is available from RSA Data Security, Inc. + * This code has been tested against that, and is equivalent, + * except that you don't need to include two pages of legalese + * with every copy. + * + * To compute the message digest of a chunk of bytes, declare an + * MD5_CTX structure, pass it to MD5Init, call MD5Update as + * needed on buffers full of bytes, and then call MD5Final, which + * will fill a supplied 16-byte array with the digest. + */ + +#include + +#include "windef.h" +#include "winbase.h" + +typedef struct +{ + unsigned int i[2]; + unsigned int buf[4]; + unsigned char in[64]; + unsigned char digest[16]; +} MD5_CTX; + +static void MD5Transform( unsigned int buf[4], const unsigned int in[16] ); + +/* + * Note: this code is harmless on little-endian machines. + */ +static void byteReverse( unsigned char *buf, unsigned longs ) +{ + unsigned int t; + + do { + t = (unsigned int)((unsigned)buf[3] << 8 | buf[2]) << 16 | + ((unsigned)buf[1] << 8 | buf[0]); + *(unsigned int *)buf = t; + buf += 4; + } while (--longs); +} + +/* + * Start MD5 accumulation. Set bit count to 0 and buffer to mysterious + * initialization constants. + */ +VOID WINAPI MD5Init( MD5_CTX *ctx ) +{ + ctx->buf[0] = 0x67452301; + ctx->buf[1] = 0xefcdab89; + ctx->buf[2] = 0x98badcfe; + ctx->buf[3] = 0x10325476; + + ctx->i[0] = ctx->i[1] = 0; +} + +/* + * Update context to reflect the concatenation of another buffer full + * of bytes. + */ +VOID WINAPI MD5Update( MD5_CTX *ctx, const unsigned char *buf, unsigned int len ) +{ + register unsigned int t; + + /* Update bitcount */ + t = ctx->i[0]; + + if ((ctx->i[0] = t + ((unsigned int)len << 3)) < t) + ctx->i[1]++; /* Carry from low to high */ + + ctx->i[1] += len >> 29; + t = (t >> 3) & 0x3f; + + /* Handle any leading odd-sized chunks */ + if (t) + { + unsigned char *p = (unsigned char *)ctx->in + t; + t = 64 - t; + + if (len < t) + { + memcpy( p, buf, len ); + return; + } + + memcpy( p, buf, t ); + byteReverse( ctx->in, 16 ); + + MD5Transform( ctx->buf, (unsigned int *)ctx->in ); + + buf += t; + len -= t; + } + + /* Process data in 64-byte chunks */ + while (len >= 64) + { + memcpy( ctx->in, buf, 64 ); + byteReverse( ctx->in, 16 ); + + MD5Transform( ctx->buf, (unsigned int *)ctx->in ); + + buf += 64; + len -= 64; + } + + /* Handle any remaining bytes of data. */ + memcpy( ctx->in, buf, len ); +} + +/* + * Final wrapup - pad to 64-byte boundary with the bit pattern + * 1 0* (64-bit count of bits processed, MSB-first) + */ +VOID WINAPI MD5Final( MD5_CTX *ctx ) +{ + unsigned int count; + unsigned char *p; + + /* Compute number of bytes mod 64 */ + count = (ctx->i[0] >> 3) & 0x3F; + + /* Set the first char of padding to 0x80. This is safe since there is + always at least one byte free */ + p = ctx->in + count; + *p++ = 0x80; + + /* Bytes of padding needed to make 64 bytes */ + count = 64 - 1 - count; + + /* Pad out to 56 mod 64 */ + if (count < 8) + { + /* Two lots of padding: Pad the first block to 64 bytes */ + memset( p, 0, count ); + byteReverse( ctx->in, 16 ); + MD5Transform( ctx->buf, (unsigned int *)ctx->in ); + + /* Now fill the next block with 56 bytes */ + memset( ctx->in, 0, 56 ); + } + else + { + /* Pad block to 56 bytes */ + memset( p, 0, count - 8 ); + } + + byteReverse( ctx->in, 14 ); + + /* Append length in bits and transform */ + ((unsigned int *)ctx->in)[14] = ctx->i[0]; + ((unsigned int *)ctx->in)[15] = ctx->i[1]; + + MD5Transform( ctx->buf, (unsigned int *)ctx->in ); + byteReverse( (unsigned char *)ctx->buf, 4 ); + memcpy( ctx->digest, ctx->buf, 16 ); +} + +/* The four core functions - F1 is optimized somewhat */ + +/* #define F1( x, y, z ) (x & y | ~x & z) */ +#define F1( x, y, z ) (z ^ (x & (y ^ z))) +#define F2( x, y, z ) F1( z, x, y ) +#define F3( x, y, z ) (x ^ y ^ z) +#define F4( x, y, z ) (y ^ (x | ~z)) + +/* This is the central step in the MD5 algorithm. */ +#define MD5STEP( f, w, x, y, z, data, s ) \ + ( w += f( x, y, z ) + data, w = w << s | w >> (32 - s), w += x ) + +/* + * The core of the MD5 algorithm, this alters an existing MD5 hash to + * reflect the addition of 16 longwords of new data. MD5Update blocks + * the data and converts bytes into longwords for this routine. + */ +static void MD5Transform( unsigned int buf[4], const unsigned int in[16] ) +{ + register unsigned int a, b, c, d; + + a = buf[0]; + b = buf[1]; + c = buf[2]; + d = buf[3]; + + MD5STEP( F1, a, b, c, d, in[0] + 0xd76aa478, 7 ); + MD5STEP( F1, d, a, b, c, in[1] + 0xe8c7b756, 12 ); + MD5STEP( F1, c, d, a, b, in[2] + 0x242070db, 17 ); + MD5STEP( F1, b, c, d, a, in[3] + 0xc1bdceee, 22 ); + MD5STEP( F1, a, b, c, d, in[4] + 0xf57c0faf, 7 ); + MD5STEP( F1, d, a, b, c, in[5] + 0x4787c62a, 12 ); + MD5STEP( F1, c, d, a, b, in[6] + 0xa8304613, 17 ); + MD5STEP( F1, b, c, d, a, in[7] + 0xfd469501, 22 ); + MD5STEP( F1, a, b, c, d, in[8] + 0x698098d8, 7 ); + MD5STEP( F1, d, a, b, c, in[9] + 0x8b44f7af, 12 ); + MD5STEP( F1, c, d, a, b, in[10] + 0xffff5bb1, 17 ); + MD5STEP( F1, b, c, d, a, in[11] + 0x895cd7be, 22 ); + MD5STEP( F1, a, b, c, d, in[12] + 0x6b901122, 7 ); + MD5STEP( F1, d, a, b, c, in[13] + 0xfd987193, 12 ); + MD5STEP( F1, c, d, a, b, in[14] + 0xa679438e, 17 ); + MD5STEP( F1, b, c, d, a, in[15] + 0x49b40821, 22 ); + + MD5STEP( F2, a, b, c, d, in[1] + 0xf61e2562, 5 ); + MD5STEP( F2, d, a, b, c, in[6] + 0xc040b340, 9 ); + MD5STEP( F2, c, d, a, b, in[11] + 0x265e5a51, 14 ); + MD5STEP( F2, b, c, d, a, in[0] + 0xe9b6c7aa, 20 ); + MD5STEP( F2, a, b, c, d, in[5] + 0xd62f105d, 5 ); + MD5STEP( F2, d, a, b, c, in[10] + 0x02441453, 9 ); + MD5STEP( F2, c, d, a, b, in[15] + 0xd8a1e681, 14 ); + MD5STEP( F2, b, c, d, a, in[4] + 0xe7d3fbc8, 20 ); + MD5STEP( F2, a, b, c, d, in[9] + 0x21e1cde6, 5 ); + MD5STEP( F2, d, a, b, c, in[14] + 0xc33707d6, 9 ); + MD5STEP( F2, c, d, a, b, in[3] + 0xf4d50d87, 14 ); + MD5STEP( F2, b, c, d, a, in[8] + 0x455a14ed, 20 ); + MD5STEP( F2, a, b, c, d, in[13] + 0xa9e3e905, 5 ); + MD5STEP( F2, d, a, b, c, in[2] + 0xfcefa3f8, 9 ); + MD5STEP( F2, c, d, a, b, in[7] + 0x676f02d9, 14 ); + MD5STEP( F2, b, c, d, a, in[12] + 0x8d2a4c8a, 20 ); + + MD5STEP( F3, a, b, c, d, in[5] + 0xfffa3942, 4 ); + MD5STEP( F3, d, a, b, c, in[8] + 0x8771f681, 11 ); + MD5STEP( F3, c, d, a, b, in[11] + 0x6d9d6122, 16 ); + MD5STEP( F3, b, c, d, a, in[14] + 0xfde5380c, 23 ); + MD5STEP( F3, a, b, c, d, in[1] + 0xa4beea44, 4 ); + MD5STEP( F3, d, a, b, c, in[4] + 0x4bdecfa9, 11 ); + MD5STEP( F3, c, d, a, b, in[7] + 0xf6bb4b60, 16 ); + MD5STEP( F3, b, c, d, a, in[10] + 0xbebfbc70, 23 ); + MD5STEP( F3, a, b, c, d, in[13] + 0x289b7ec6, 4 ); + MD5STEP( F3, d, a, b, c, in[0] + 0xeaa127fa, 11 ); + MD5STEP( F3, c, d, a, b, in[3] + 0xd4ef3085, 16 ); + MD5STEP( F3, b, c, d, a, in[6] + 0x04881d05, 23 ); + MD5STEP( F3, a, b, c, d, in[9] + 0xd9d4d039, 4 ); + MD5STEP( F3, d, a, b, c, in[12] + 0xe6db99e5, 11 ); + MD5STEP( F3, c, d, a, b, in[15] + 0x1fa27cf8, 16 ); + MD5STEP( F3, b, c, d, a, in[2] + 0xc4ac5665, 23 ); + + MD5STEP( F4, a, b, c, d, in[0] + 0xf4292244, 6 ); + MD5STEP( F4, d, a, b, c, in[7] + 0x432aff97, 10 ); + MD5STEP( F4, c, d, a, b, in[14] + 0xab9423a7, 15 ); + MD5STEP( F4, b, c, d, a, in[5] + 0xfc93a039, 21 ); + MD5STEP( F4, a, b, c, d, in[12] + 0x655b59c3, 6 ); + MD5STEP( F4, d, a, b, c, in[3] + 0x8f0ccc92, 10 ); + MD5STEP( F4, c, d, a, b, in[10] + 0xffeff47d, 15 ); + MD5STEP( F4, b, c, d, a, in[1] + 0x85845dd1, 21 ); + MD5STEP( F4, a, b, c, d, in[8] + 0x6fa87e4f, 6 ); + MD5STEP( F4, d, a, b, c, in[15] + 0xfe2ce6e0, 10 ); + MD5STEP( F4, c, d, a, b, in[6] + 0xa3014314, 15 ); + MD5STEP( F4, b, c, d, a, in[13] + 0x4e0811a1, 21 ); + MD5STEP( F4, a, b, c, d, in[4] + 0xf7537e82, 6 ); + MD5STEP( F4, d, a, b, c, in[11] + 0xbd3af235, 10 ); + MD5STEP( F4, c, d, a, b, in[2] + 0x2ad7d2bb, 15 ); + MD5STEP( F4, b, c, d, a, in[9] + 0xeb86d391, 21 ); + + buf[0] += a; + buf[1] += b; + buf[2] += c; + buf[3] += d; +} diff --git a/reactos/lib/advapi32/crypt/crypt_sha.c b/reactos/lib/advapi32/crypt/crypt_sha.c new file mode 100644 index 00000000000..e8f77159028 --- /dev/null +++ b/reactos/lib/advapi32/crypt/crypt_sha.c @@ -0,0 +1,188 @@ +/* + * Copyright 2004 Filip Navara + * Based on public domain SHA code by Steve Reid + * + * 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 + */ + +#include +#include "windef.h" +#include "winbase.h" + +/* SHA Context Structure Declaration */ + +typedef struct { + ULONG Unknown[6]; + ULONG State[5]; + ULONG Count[2]; + UCHAR Buffer[64]; +} SHA_CTX, *PSHA_CTX; + +/* SHA1 Helper Macros */ + +#define rol(value, bits) (((value) << (bits)) | ((value) >> (32 - (bits)))) +/* FIXME: This definition of DWORD2BE is little endian specific! */ +#define DWORD2BE(x) (((x) >> 24) & 0xff) | (((x) >> 8) & 0xff00) | (((x) << 8) & 0xff0000) | (((x) << 24) & 0xff000000); +/* FIXME: This definition of blk0 is little endian specific! */ +#define blk0(i) (Block[i] = (rol(Block[i],24)&0xFF00FF00)|(rol(Block[i],8)&0x00FF00FF)) +#define blk1(i) (Block[i&15] = rol(Block[(i+13)&15]^Block[(i+8)&15]^Block[(i+2)&15]^Block[i&15],1)) +#define f1(x,y,z) (z^(x&(y^z))) +#define f2(x,y,z) (x^y^z) +#define f3(x,y,z) ((x&y)|(z&(x|y))) +#define f4(x,y,z) (x^y^z) +/* (R0+R1), R2, R3, R4 are the different operations used in SHA1 */ +#define R0(v,w,x,y,z,i) z+=f1(w,x,y)+blk0(i)+0x5A827999+rol(v,5);w=rol(w,30); +#define R1(v,w,x,y,z,i) z+=f1(w,x,y)+blk1(i)+0x5A827999+rol(v,5);w=rol(w,30); +#define R2(v,w,x,y,z,i) z+=f2(w,x,y)+blk1(i)+0x6ED9EBA1+rol(v,5);w=rol(w,30); +#define R3(v,w,x,y,z,i) z+=f3(w,x,y)+blk1(i)+0x8F1BBCDC+rol(v,5);w=rol(w,30); +#define R4(v,w,x,y,z,i) z+=f4(w,x,y)+blk1(i)+0xCA62C1D6+rol(v,5);w=rol(w,30); + +/* Hash a single 512-bit block. This is the core of the algorithm. */ +void SHA1Transform(ULONG State[5], CHAR Buffer[64]) +{ + ULONG a, b, c, d, e; + ULONG *Block; + + Block = (ULONG*)Buffer; + + /* Copy Context->State[] to working variables */ + a = State[0]; + b = State[1]; + c = State[2]; + d = State[3]; + e = State[4]; + + /* 4 rounds of 20 operations each. Loop unrolled. */ + R0(a,b,c,d,e, 0); R0(e,a,b,c,d, 1); R0(d,e,a,b,c, 2); R0(c,d,e,a,b, 3); + R0(b,c,d,e,a, 4); R0(a,b,c,d,e, 5); R0(e,a,b,c,d, 6); R0(d,e,a,b,c, 7); + R0(c,d,e,a,b, 8); R0(b,c,d,e,a, 9); R0(a,b,c,d,e,10); R0(e,a,b,c,d,11); + R0(d,e,a,b,c,12); R0(c,d,e,a,b,13); R0(b,c,d,e,a,14); R0(a,b,c,d,e,15); + R1(e,a,b,c,d,16); R1(d,e,a,b,c,17); R1(c,d,e,a,b,18); R1(b,c,d,e,a,19); + R2(a,b,c,d,e,20); R2(e,a,b,c,d,21); R2(d,e,a,b,c,22); R2(c,d,e,a,b,23); + R2(b,c,d,e,a,24); R2(a,b,c,d,e,25); R2(e,a,b,c,d,26); R2(d,e,a,b,c,27); + R2(c,d,e,a,b,28); R2(b,c,d,e,a,29); R2(a,b,c,d,e,30); R2(e,a,b,c,d,31); + R2(d,e,a,b,c,32); R2(c,d,e,a,b,33); R2(b,c,d,e,a,34); R2(a,b,c,d,e,35); + R2(e,a,b,c,d,36); R2(d,e,a,b,c,37); R2(c,d,e,a,b,38); R2(b,c,d,e,a,39); + R3(a,b,c,d,e,40); R3(e,a,b,c,d,41); R3(d,e,a,b,c,42); R3(c,d,e,a,b,43); + R3(b,c,d,e,a,44); R3(a,b,c,d,e,45); R3(e,a,b,c,d,46); R3(d,e,a,b,c,47); + R3(c,d,e,a,b,48); R3(b,c,d,e,a,49); R3(a,b,c,d,e,50); R3(e,a,b,c,d,51); + R3(d,e,a,b,c,52); R3(c,d,e,a,b,53); R3(b,c,d,e,a,54); R3(a,b,c,d,e,55); + R3(e,a,b,c,d,56); R3(d,e,a,b,c,57); R3(c,d,e,a,b,58); R3(b,c,d,e,a,59); + R4(a,b,c,d,e,60); R4(e,a,b,c,d,61); R4(d,e,a,b,c,62); R4(c,d,e,a,b,63); + R4(b,c,d,e,a,64); R4(a,b,c,d,e,65); R4(e,a,b,c,d,66); R4(d,e,a,b,c,67); + R4(c,d,e,a,b,68); R4(b,c,d,e,a,69); R4(a,b,c,d,e,70); R4(e,a,b,c,d,71); + R4(d,e,a,b,c,72); R4(c,d,e,a,b,73); R4(b,c,d,e,a,74); R4(a,b,c,d,e,75); + R4(e,a,b,c,d,76); R4(d,e,a,b,c,77); R4(c,d,e,a,b,78); R4(b,c,d,e,a,79); + + /* Add the working variables back into Context->State[] */ + State[0] += a; + State[1] += b; + State[2] += c; + State[3] += d; + State[4] += e; + + /* Wipe variables */ + a = b = c = d = e = 0; +} + + +/****************************************************************************** + * A_SHAInit [ADVAPI32.@] + * + * Initialize a SHA context structure. + */ +VOID WINAPI +A_SHAInit(PSHA_CTX Context) +{ + /* SHA1 initialization constants */ + Context->State[0] = 0x67452301; + Context->State[1] = 0xEFCDAB89; + Context->State[2] = 0x98BADCFE; + Context->State[3] = 0x10325476; + Context->State[4] = 0xC3D2E1F0; + Context->Count[0] = + Context->Count[1] = 0; +} + +/****************************************************************************** + * A_SHAUpdate [ADVAPI32.@] + * + * Update a SHA context with a hashed data from supplied buffer. + */ +VOID WINAPI +A_SHAUpdate(PSHA_CTX Context, PCHAR Buffer, UINT BufferSize) +{ + ULONG BufferContentSize; + + BufferContentSize = Context->Count[1] & 63; + Context->Count[1] += BufferSize; + if (Context->Count[1] < BufferSize) + Context->Count[0]++; + Context->Count[0] += (BufferSize >> 29); + + if (BufferContentSize + BufferSize < 64) + { + RtlCopyMemory(&Context->Buffer[BufferContentSize], Buffer, + BufferSize); + } + else + { + while (BufferContentSize + BufferSize >= 64) + { + RtlCopyMemory(Context->Buffer + BufferContentSize, Buffer, + 64 - BufferContentSize); + Buffer += 64 - BufferContentSize; + BufferSize -= 64 - BufferContentSize; + SHA1Transform(Context->State, Context->Buffer); + BufferContentSize = 0; + } + RtlCopyMemory(Context->Buffer + BufferContentSize, Buffer, BufferSize); + } +} + +/****************************************************************************** + * A_SHAFinal [ADVAPI32.@] + * + * Finalize SHA context and return the resulting hash. + */ +VOID WINAPI +A_SHAFinal(PSHA_CTX Context, PULONG Result) +{ + INT Pad, Index; + UCHAR Buffer[72]; + ULONG *Count; + ULONG BufferContentSize, LengthHi, LengthLo; + + BufferContentSize = Context->Count[1] & 63; + if (BufferContentSize >= 56) + Pad = 56 + 64 - BufferContentSize; + else + Pad = 56 - BufferContentSize; + + LengthHi = (Context->Count[0] << 3) | (Context->Count[1] >> (32 - 3)); + LengthLo = (Context->Count[1] << 3); + + RtlZeroMemory(Buffer + 1, Pad - 1); + Buffer[0] = 0x80; + Count = (ULONG*)(Buffer + Pad); + Count[0] = DWORD2BE(LengthHi); + Count[1] = DWORD2BE(LengthLo); + A_SHAUpdate(Context, Buffer, Pad + 8); + + for (Index = 0; Index < 5; Index++) + Result[Index] = DWORD2BE(Context->State[Index]); + + A_SHAInit(Context); +} diff --git a/reactos/lib/advapi32/makefile b/reactos/lib/advapi32/makefile index 574c29c1a02..71207234b79 100644 --- a/reactos/lib/advapi32/makefile +++ b/reactos/lib/advapi32/makefile @@ -1,4 +1,4 @@ -# $Id: makefile,v 1.42 2004/08/15 17:03:14 chorns Exp $ +# $Id: makefile,v 1.43 2004/12/11 00:21:33 weiden Exp $ PATH_TO_TOP = ../.. @@ -13,10 +13,18 @@ TARGET_CFLAGS = -Wall -Werror -fno-builtin -D__USE_W32API TARGET_LFLAGS = -nostartfiles -nostdlib -TARGET_SDKLIBS = ntdll.a kernel32.a +TARGET_SDKLIBS = wine.a ntdll.a kernel32.a TARGET_BASE = $(TARGET_BASE_LIB_ADVAPI32) +CRYPT_OBJECTS = \ + crypt/crypt_des.o \ + crypt/crypt_lmhash.o \ + crypt/crypt_md4.o \ + crypt/crypt_md5.o \ + crypt/crypt_sha.o \ + crypt/crypt.o + MISC_OBJECTS = \ misc/dllmain.o \ misc/hwprofiles.o \ @@ -33,7 +41,8 @@ SECURITY_OBJECTS = \ sec/lsa.o \ sec/misc.o \ sec/sec.o \ - sec/sid.o + sec/sid.o \ + sec/trustee.o SERVICE_OBJECTS = \ service/eventlog.o \ @@ -46,6 +55,7 @@ TOKEN_OBJECTS = \ token/token.o TARGET_OBJECTS = \ + $(CRYPT_OBJECTS) \ $(MISC_OBJECTS) \ $(REGISTRY_OBJECTS) \ $(SECURITY_OBJECTS) \ diff --git a/reactos/lib/advapi32/misc/sysfunc.c b/reactos/lib/advapi32/misc/sysfunc.c index e6c09a5cf7c..bb2cb09f5f0 100644 --- a/reactos/lib/advapi32/misc/sysfunc.c +++ b/reactos/lib/advapi32/misc/sysfunc.c @@ -1,4 +1,4 @@ -/* $Id: sysfunc.c,v 1.8 2004/08/15 17:03:14 chorns Exp $ +/* $Id: sysfunc.c,v 1.9 2004/12/11 00:21:33 weiden Exp $ * * COPYRIGHT: See COPYING in the top level directory * PROJECT: ReactOS system libraries @@ -77,20 +77,6 @@ SystemFunction005(INT a, INT b, INT c) return 5; } - -/********************************************************************** - * - * @unimplemented - */ -INT -STDCALL -SystemFunction006(INT a, INT b) -{ - SetLastError(ERROR_CALL_NOT_IMPLEMENTED); - return 6; -} - - /********************************************************************** * * @unimplemented diff --git a/reactos/lib/advapi32/sec/trustee.c b/reactos/lib/advapi32/sec/trustee.c new file mode 100644 index 00000000000..61402fa5da5 --- /dev/null +++ b/reactos/lib/advapi32/sec/trustee.c @@ -0,0 +1,68 @@ +/* $Id: trustee.c,v 1.1 2004/12/11 00:21:33 weiden Exp $ + * + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS system libraries + * FILE: lib/advapi32/sec/ac.c + * PURPOSE: ACL/ACE functions + */ + +#include "advapi32.h" + +#include "wine/debug.h" + + +/****************************************************************************** + * BuildTrusteeWithSidA [ADVAPI32.@] + */ +VOID WINAPI BuildTrusteeWithSidA(PTRUSTEEA pTrustee, PSID pSid) +{ + DPRINT("%p %p\n", pTrustee, pSid); + + pTrustee->pMultipleTrustee = NULL; + pTrustee->MultipleTrusteeOperation = NO_MULTIPLE_TRUSTEE; + pTrustee->TrusteeForm = TRUSTEE_IS_SID; + pTrustee->TrusteeType = TRUSTEE_IS_UNKNOWN; + pTrustee->ptstrName = (LPSTR) pSid; +} + +/****************************************************************************** + * BuildTrusteeWithSidW [ADVAPI32.@] + */ +VOID WINAPI BuildTrusteeWithSidW(PTRUSTEEW pTrustee, PSID pSid) +{ + DPRINT("%p %p\n", pTrustee, pSid); + + pTrustee->pMultipleTrustee = NULL; + pTrustee->MultipleTrusteeOperation = NO_MULTIPLE_TRUSTEE; + pTrustee->TrusteeForm = TRUSTEE_IS_SID; + pTrustee->TrusteeType = TRUSTEE_IS_UNKNOWN; + pTrustee->ptstrName = (LPWSTR) pSid; +} + +/****************************************************************************** + * BuildTrusteeWithNameA [ADVAPI32.@] + */ +VOID WINAPI BuildTrusteeWithNameA(PTRUSTEEA pTrustee, LPSTR name) +{ + DPRINT("%p %s\n", pTrustee, debugstr_a(name) ); + + pTrustee->pMultipleTrustee = NULL; + pTrustee->MultipleTrusteeOperation = NO_MULTIPLE_TRUSTEE; + pTrustee->TrusteeForm = TRUSTEE_IS_NAME; + pTrustee->TrusteeType = TRUSTEE_IS_UNKNOWN; + pTrustee->ptstrName = name; +} + +/****************************************************************************** + * BuildTrusteeWithNameW [ADVAPI32.@] + */ +VOID WINAPI BuildTrusteeWithNameW(PTRUSTEEW pTrustee, LPWSTR name) +{ + DPRINT("%p %s\n", pTrustee, debugstr_w(name) ); + + pTrustee->pMultipleTrustee = NULL; + pTrustee->MultipleTrusteeOperation = NO_MULTIPLE_TRUSTEE; + pTrustee->TrusteeForm = TRUSTEE_IS_NAME; + pTrustee->TrusteeType = TRUSTEE_IS_UNKNOWN; + pTrustee->ptstrName = name; +} diff --git a/reactos/lib/advapi32/token/token.c b/reactos/lib/advapi32/token/token.c index 3374d021ac5..42f6fee774b 100644 --- a/reactos/lib/advapi32/token/token.c +++ b/reactos/lib/advapi32/token/token.c @@ -1,4 +1,4 @@ -/* $Id: token.c,v 1.15 2004/12/10 16:50:37 navaraf Exp $ +/* $Id: token.c,v 1.16 2004/12/11 00:21:33 weiden Exp $ * * COPYRIGHT: See COPYING in the top level directory * PROJECT: ReactOS system libraries @@ -259,15 +259,9 @@ DuplicateTokenEx (HANDLE ExistingTokenHandle, PHANDLE DuplicateTokenHandle) { OBJECT_ATTRIBUTES ObjectAttributes; - SECURITY_QUALITY_OF_SERVICE Qos; HANDLE NewToken; NTSTATUS Status; - Qos.Length = sizeof(SECURITY_QUALITY_OF_SERVICE); - Qos.ImpersonationLevel = ImpersonationLevel; - Qos.ContextTrackingMode = SECURITY_DYNAMIC_TRACKING; - Qos.EffectiveOnly = FALSE; - ObjectAttributes.Length = sizeof(OBJECT_ATTRIBUTES); ObjectAttributes.RootDirectory = NULL; ObjectAttributes.ObjectName = NULL; @@ -277,12 +271,12 @@ DuplicateTokenEx (HANDLE ExistingTokenHandle, ObjectAttributes.Attributes |= OBJ_INHERIT; } ObjectAttributes.SecurityDescriptor = lpTokenAttributes->lpSecurityDescriptor; - ObjectAttributes.SecurityQualityOfService = &Qos; + ObjectAttributes.SecurityQualityOfService = NULL; Status = NtDuplicateToken (ExistingTokenHandle, dwDesiredAccess, &ObjectAttributes, - FALSE, + ImpersonationLevel, TokenType, &NewToken); if (!NT_SUCCESS(Status))