crypt.c 66.6 KB
Newer Older
1
/*
2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
 * 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
17
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
18
 */
19

20 21 22 23 24 25
/***********************************************************************
 *
 *  TODO:
 *  - Reference counting
 *  - Thread-safing
 */
26

27
#include "config.h"
28
#include "wine/port.h"
29

30
#include <limits.h>
31 32
#include <time.h>
#include <stdlib.h>
33
#include <stdio.h>
34
#include <sys/types.h>
35 36 37
#ifdef HAVE_SYS_STAT_H
# include <sys/stat.h>
#endif
38
#include <fcntl.h>
39 40 41
#ifdef HAVE_UNISTD_H
# include <unistd.h>
#endif
42

43 44
#include "ntstatus.h"
#define WIN32_NO_STATUS
45 46 47
#include "crypt.h"
#include "winnls.h"
#include "winreg.h"
48
#include "rpc.h"
49
#include "wine/debug.h"
50
#include "wine/unicode.h"
51
#include "winternl.h"
52

53
WINE_DEFAULT_DEBUG_CHANNEL(crypt);
54

55
static HWND crypt_hWindow;
56

57
#define CRYPT_Alloc(size) (LocalAlloc(LMEM_ZEROINIT, size))
58
#define CRYPT_Free(buffer) (LocalFree(buffer))
59

60
static inline PWSTR CRYPT_GetProvKeyName(PCWSTR pProvName)
61
{
62 63 64 65 66 67 68 69
	static const WCHAR KEYSTR[] = {
                '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
	};
	PWSTR keyname;
70

71
	keyname = CRYPT_Alloc((strlenW(KEYSTR) + strlenW(pProvName) +1)*sizeof(WCHAR));
72 73
	if (keyname)
	{
74 75
		strcpyW(keyname, KEYSTR);
		strcpyW(keyname + strlenW(KEYSTR), pProvName);
76 77 78 79 80
	} else
		SetLastError(ERROR_NOT_ENOUGH_MEMORY);
	return keyname;
}

81
static inline PWSTR CRYPT_GetTypeKeyName(DWORD dwType, BOOL user)
82
{
83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98
	static const WCHAR MACHINESTR[] = {
                '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',' ','T','y','p','e','s','\\',
                'T','y','p','e',' ','X','X','X',0
	};
	static const WCHAR USERSTR[] = {
                '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','\\',
                'P','r','o','v','i','d','e','r',' ','T','y','p','e',' ','X','X','X',0
	};
	PWSTR keyname;
	PWSTR ptr;
99

100
	keyname = CRYPT_Alloc( ((user ? strlenW(USERSTR) : strlenW(MACHINESTR)) +1)*sizeof(WCHAR));
101 102
	if (keyname)
	{
103 104
		user ? strcpyW(keyname, USERSTR) : strcpyW(keyname, MACHINESTR);
		ptr = keyname + strlenW(keyname);
105
		*(--ptr) = (dwType % 10) + '0';
106
		*(--ptr) = ((dwType / 10) % 10) + '0';
107 108 109 110 111 112
		*(--ptr) = (dwType / 100) + '0';
	} else
		SetLastError(ERROR_NOT_ENOUGH_MEMORY);
	return keyname;
}

113
/* CRYPT_UnicodeToANSI
114
 * wstr - unicode string
115 116
 * str - pointer to ANSI string or pointer to null pointer if we have to do the allocation
 * strsize - size of buffer pointed to by str
117
 *
118
 * returns TRUE if unsuccessful, FALSE otherwise.
119 120 121 122 123 124 125 126 127
 * 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)
{
	if (!wstr)
	{
		*str = NULL;
		return TRUE;
	}
128 129 130 131 132 133 134 135 136 137 138

	if (!*str)
	{
		strsize = WideCharToMultiByte(CP_ACP, 0, wstr, -1, NULL, 0, NULL, NULL);
		*str = CRYPT_Alloc(strsize * sizeof(CHAR));
	}
	else if (strsize < 0)
	{
		strsize = INT_MAX; /* windows will pretend that the buffer is infinitely long */
	}

139 140
	if (*str)
	{
141
		WideCharToMultiByte(CP_ACP, 0, wstr, -1, *str, strsize, NULL, NULL);
142 143
		return TRUE;
	}
144

145 146 147 148 149 150 151 152 153 154 155
	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)
{
156
	unsigned int wcount;
157 158 159 160 161 162 163 164 165

	if (!str)
	{
		*wstr = NULL;
		return TRUE;
	}
	wcount = MultiByteToWideChar(CP_ACP, 0, str, -1, NULL, 0);
	if (wstrsize == -1)
		*wstr = CRYPT_Alloc(wcount * sizeof(WCHAR));
166 167
	else
		wcount = min( wcount, wstrsize/sizeof(WCHAR) );
168 169 170 171 172 173 174 175 176
	if (*wstr)
	{
		MultiByteToWideChar(CP_ACP, 0, str, -1, *wstr, wcount);
		return TRUE;
	}
	SetLastError(ERROR_NOT_ENOUGH_MEMORY);
	return FALSE;
}

177
/* These next 2 functions are used by the VTableProvStruc structure */
178
static BOOL CALLBACK CRYPT_VerifyImage(LPCSTR lpszImage, BYTE* pData)
179 180 181 182 183 184
{
	if (!lpszImage || !pData)
	{
		SetLastError(ERROR_INVALID_PARAMETER);
		return FALSE;
	}
185

186
	FIXME("(%s, %p): not verifying image\n", lpszImage, pData);
187

188 189 190
	return TRUE;
}

191
static void CALLBACK CRYPT_ReturnhWnd(HWND *phWnd)
192
{
193
	if (phWnd) *phWnd = crypt_hWindow;
194 195 196 197 198 199
}

#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)
200
static PCRYPTPROV CRYPT_LoadProvider(PCWSTR pImage)
201 202 203 204 205 206 207
{
	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;
208
	if ( !(provider->hModule = LoadLibraryW(pImage)) )
209 210
	{
		errorcode = (GetLastError() == ERROR_FILE_NOT_FOUND) ? NTE_PROV_DLL_NOT_FOUND : NTE_PROVIDER_DLL_FAIL;
211
		FIXME("Failed to load dll %s\n", debugstr_w(pImage));
212 213
		goto error;
	}
214
	provider->dwMagic = MAGIC_CRYPTPROV;
215
	provider->refcount = 1;
216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243

	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);

244 245 246
	/* FIXME: Not sure what the pbContextInfo field is for.
	 *        Does it need memory allocation?
         */
247
	provider->pVTable->Version = 3;
248 249
	provider->pVTable->FuncVerifyImage = CRYPT_VerifyImage;
	provider->pVTable->FuncReturnhWnd = CRYPT_ReturnhWnd;
250 251 252 253 254 255 256 257 258 259
	provider->pVTable->dwProvType = 0;
	provider->pVTable->pbContextInfo = NULL;
	provider->pVTable->cbContextInfo = 0;
	provider->pVTable->pszProvName = NULL;
	return provider;

error:
	SetLastError(errorcode);
	if (provider)
	{
260
		provider->dwMagic = 0;
261 262 263 264 265 266 267 268 269 270 271
		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

272

273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292
static void CRYPT_CreateMachineGuid(void)
{
	static const WCHAR cryptographyW[] = {
                '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',0 };
	static const WCHAR machineGuidW[] = {
		'M','a','c','h','i','n','e','G','u','i','d',0 };
	LONG r;
	HKEY key;

	r = RegOpenKeyExW(HKEY_LOCAL_MACHINE, cryptographyW, 0, KEY_ALL_ACCESS,
			  &key);
	if (!r)
	{
		DWORD size;

		r = RegQueryValueExW(key, machineGuidW, NULL, NULL, NULL, &size);
		if (r == ERROR_FILE_NOT_FOUND)
		{
293 294 295 296 297 298 299 300 301 302
                    UUID uuid;
                    WCHAR buf[37];
                    RPC_STATUS rs;
                    static const WCHAR uuidFmt[] = {
                        '%','0','8','x','-','%','0','4','x','-',
                        '%','0','4','x','-','%','0','2','x',
                        '%','0','2','x','-','%','0','2','x',
                        '%','0','2','x','%','0','2','x',
                        '%','0','2','x','%','0','2','x',
                        '%','0','2','x',0 };
303

304 305 306 307 308 309 310 311 312 313 314 315 316
                    rs = UuidCreate(&uuid);
                    if (rs == S_OK)
                    {
                        sprintfW(buf, uuidFmt,
                                 uuid.Data1, uuid.Data2, uuid.Data3,
                                 uuid.Data4[0], uuid.Data4[1],
                                 uuid.Data4[2], uuid.Data4[3],
                                 uuid.Data4[4], uuid.Data4[5],
                                 uuid.Data4[6], uuid.Data4[7] );
                        RegSetValueExW(key, machineGuidW, 0, REG_SZ,
                                       (const BYTE *)buf,
                                       (lstrlenW(buf)+1)*sizeof(WCHAR));
                    }
317 318 319 320 321
		}
		RegCloseKey(key);
	}
}

322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338

/******************************************************************************
 * CloseEncryptedFileRaw   (ADVAPI32.@)
 *
 * Close encrypted files
 *
 * PARAMS
 *  context    [I] pointer to the context
 * RETURNS
 *  Success: ERROR_SUCCESS
 *  Failure: NTSTATUS error code
 */
void WINAPI CloseEncryptedFileRaw(PVOID context)
{
    FIXME("(%p): stub\n", context);
}

339
/******************************************************************************
340
 * CryptAcquireContextW (ADVAPI32.@)
341
 *
342
 * Acquire a crypto provider context handle.
343
 *
344
 * PARAMS
345 346 347 348 349 350 351 352
 *  phProv       [O] Pointer to HCRYPTPROV for the output.
 *  pszContainer [I] Key Container Name
 *  pszProvider  [I] Cryptographic Service Provider Name
 *  dwProvType   [I] Crypto provider type to get a handle.
 *  dwFlags      [I] flags for the operation
 *
 * RETURNS 
 *  TRUE on success, FALSE on failure.
353
 */
354 355
BOOL WINAPI CryptAcquireContextW (HCRYPTPROV *phProv, LPCWSTR pszContainer,
		LPCWSTR pszProvider, DWORD dwProvType, DWORD dwFlags)
356
{
357 358
	PCRYPTPROV pProv = NULL;
	HKEY key;
359 360
	PWSTR imagepath = NULL, keyname = NULL, provname = NULL, temp = NULL;
	PSTR provnameA = NULL, pszContainerA = NULL;
361
	DWORD keytype, type, len;
362
	ULONG r;
363 364 365
	static const WCHAR nameW[] = {'N','a','m','e',0};
	static const WCHAR typeW[] = {'T','y','p','e',0};
	static const WCHAR imagepathW[] = {'I','m','a','g','e',' ','P','a','t','h',0};
366

367
	TRACE("(%p, %s, %s, %d, %08x)\n", phProv, debugstr_w(pszContainer),
368
		debugstr_w(pszProvider), dwProvType, dwFlags);
369

370
	if (dwProvType < 1 || dwProvType > MAXPROVTYPES)
371
	{
372
		SetLastError(NTE_BAD_PROV_TYPE);
373 374
		return FALSE;
	}
375 376
	
	if (!phProv)
377
	{
378
		SetLastError(ERROR_INVALID_PARAMETER);
379 380 381
		return FALSE;
	}

382 383 384
	/* Make sure the MachineGuid value exists */
	CRYPT_CreateMachineGuid();

385
	if (!pszProvider || !*pszProvider)
386
	{
387 388 389
		/* No CSP name specified so try the user default CSP first
		 * then try the machine default CSP
		 */
390
		if ( !(keyname = CRYPT_GetTypeKeyName(dwProvType, TRUE)) ) {
391
			TRACE("No provider registered for crypto provider type %d.\n", dwProvType);
392 393
			SetLastError(NTE_PROV_TYPE_NOT_DEF);
			return FALSE;
394
		}
395
		if (RegOpenKeyW(HKEY_CURRENT_USER, keyname, &key))
396 397
		{
			CRYPT_Free(keyname);
398
			if ( !(keyname = CRYPT_GetTypeKeyName(dwProvType, FALSE)) ) {
399
				TRACE("No type registered for crypto provider type %d.\n", dwProvType);
400 401 402
				RegCloseKey(key);
				SetLastError(NTE_PROV_TYPE_NOT_DEF);
				goto error;
403
			}
404 405
			if (RegOpenKeyW(HKEY_LOCAL_MACHINE, keyname, &key)) {
				TRACE("Did not find registry entry of crypto provider for %s.\n", debugstr_w(keyname));
406
				CRYPT_Free(keyname);
407 408
				RegCloseKey(key);
				SetLastError(NTE_PROV_TYPE_NOT_DEF);
409 410
				goto error;
			}
411 412
		}
		CRYPT_Free(keyname);
413
		r = RegQueryValueExW(key, nameW, NULL, &keytype, NULL, &len);
414
		if( r != ERROR_SUCCESS || !len || keytype != REG_SZ)
415
		{
416
			TRACE("error %d reading size of 'Name' from registry\n", r );
417 418 419 420 421 422 423 424 425 426
			RegCloseKey(key);
			SetLastError(NTE_PROV_TYPE_ENTRY_BAD);
			goto error;
		}
		if(!(provname = CRYPT_Alloc(len)))
		{
			RegCloseKey(key);
			SetLastError(ERROR_NOT_ENOUGH_MEMORY);
			goto error;
		}
427
		r = RegQueryValueExW(key, nameW, NULL, NULL, (LPBYTE)provname, &len);
428 429
		if( r != ERROR_SUCCESS )
		{
430
			TRACE("error %d reading 'Name' from registry\n", r );
431 432 433 434
			RegCloseKey(key);
			SetLastError(NTE_PROV_TYPE_ENTRY_BAD);
			goto error;
		}
435 436
		RegCloseKey(key);
	} else {
437
		if ( !(provname = CRYPT_Alloc((strlenW(pszProvider) +1)*sizeof(WCHAR))) )
438
		{
439
			SetLastError(ERROR_NOT_ENOUGH_MEMORY);
440 441
			goto error;
		}
442
		strcpyW(provname, pszProvider);
443 444 445
	}

	keyname = CRYPT_GetProvKeyName(provname);
446
	r = RegOpenKeyW(HKEY_LOCAL_MACHINE, keyname, &key);
447
	CRYPT_Free(keyname);
448 449 450 451 452
	if (r != ERROR_SUCCESS)
	{
		SetLastError(NTE_KEYSET_NOT_DEF);
		goto error;
	}
453
	len = sizeof(DWORD);
454
	r = RegQueryValueExW(key, typeW, NULL, NULL, (BYTE*)&type, &len);
455
	if (r != ERROR_SUCCESS)
456
	{
457 458 459 460 461
		SetLastError(NTE_PROV_TYPE_ENTRY_BAD);
		goto error;
	}
	if (type != dwProvType)
	{
462
		TRACE("Crypto provider has wrong type (%d vs expected %d).\n", type, dwProvType);
463
		SetLastError(NTE_PROV_TYPE_NO_MATCH);
464 465 466
		goto error;
	}

467
	r = RegQueryValueExW(key, imagepathW, NULL, &keytype, NULL, &len);
468
	if ( r != ERROR_SUCCESS || keytype != REG_SZ)
469
	{
470
		TRACE("error %d reading size of 'Image Path' from registry\n", r );
471 472 473 474 475 476 477 478 479 480
		RegCloseKey(key);
		SetLastError(NTE_PROV_TYPE_ENTRY_BAD);
		goto error;
	}
	if (!(temp = CRYPT_Alloc(len)))
	{
		RegCloseKey(key);
		SetLastError(ERROR_NOT_ENOUGH_MEMORY);
		goto error;
	}
481
	r = RegQueryValueExW(key, imagepathW, NULL, NULL, (LPBYTE)temp, &len);
482 483
	if( r != ERROR_SUCCESS )
	{
484
		TRACE("error %d reading 'Image Path' from registry\n", r );
485 486 487 488
		RegCloseKey(key);
		SetLastError(NTE_PROV_TYPE_ENTRY_BAD);
		goto error;
	}
489
	RegCloseKey(key);
490 491
	len = ExpandEnvironmentStringsW(temp, NULL, 0);
	if ( !(imagepath = CRYPT_Alloc(len*sizeof(WCHAR))) )
492 493 494 495
	{
		SetLastError(ERROR_NOT_ENOUGH_MEMORY);
		goto error;
	}
496
	if (!ExpandEnvironmentStringsW(temp, imagepath, len))
497 498 499 500
	{
		/* ExpandEnvironmentStrings will call SetLastError */
		goto error;
	}
501
	pProv = CRYPT_LoadProvider(imagepath);
502
	if (!pProv) {
503
		/* CRYPT_LoadProvider calls SetLastError */
504 505
		goto error;
	}
506
	pProv->pVTable->dwProvType = dwProvType;
507
	if(!CRYPT_UnicodeToANSI(provname, &provnameA, 0))
508 509 510 511 512
	{
		/* CRYPT_UnicodeToANSI calls SetLastError */
		goto error;
	}
	pProv->pVTable->pszProvName = provnameA;
513
	if(!CRYPT_UnicodeToANSI(pszContainer, &pszContainerA, 0))
514 515 516 517 518
	{
		/* CRYPT_UnicodeToANSI calls SetLastError */
		goto error;
	}
	if (pProv->pFuncs->pCPAcquireContext(&pProv->hPrivate, pszContainerA, dwFlags, pProv->pVTable))
519
	{
520 521 522
		/* 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.
523
		 */
524 525
		if (dwFlags & CRYPT_DELETEKEYSET)
		{
526
			pProv->dwMagic = 0;
527
			FreeLibrary(pProv->hModule);
528 529
			CRYPT_Free(provnameA);
			CRYPT_Free(pProv->pVTable);
530 531 532 533 534
			CRYPT_Free(pProv->pFuncs);
			CRYPT_Free(pProv);
		} else {
			*phProv = (HCRYPTPROV)pProv;
		}
535 536
		CRYPT_Free(pszContainerA);
		CRYPT_Free(provname);
537 538
		CRYPT_Free(temp);
		CRYPT_Free(imagepath);
539 540
		return TRUE;
	}
541
	/* FALLTHROUGH TO ERROR IF FALSE - CSP internal error! */
542 543 544
error:
	if (pProv)
	{
545
		pProv->dwMagic = 0;
546 547
		if (pProv->hModule)
			FreeLibrary(pProv->hModule);
548 549
		CRYPT_Free(pProv->pVTable);
		CRYPT_Free(pProv->pFuncs);
550 551
		CRYPT_Free(pProv);
	}
552 553 554 555 556
	CRYPT_Free(pszContainerA);
	CRYPT_Free(provnameA);
	CRYPT_Free(provname);
	CRYPT_Free(temp);
	CRYPT_Free(imagepath);
557 558
	return FALSE;
}
559

560
/******************************************************************************
561
 * CryptAcquireContextA (ADVAPI32.@)
562
 *
563
 * See CryptAcquireContextW.
564
 */
565 566
BOOL WINAPI CryptAcquireContextA (HCRYPTPROV *phProv, LPCSTR pszContainer,
		LPCSTR pszProvider, DWORD dwProvType, DWORD dwFlags)
567
{
568
	PWSTR pProvider = NULL, pContainer = NULL;
569 570
	BOOL ret = FALSE;

571 572
	TRACE("(%p, %s, %s, %d, %08x)\n", phProv, debugstr_a(pszContainer),
              debugstr_a(pszProvider), dwProvType, dwFlags);
573

574
	if ( !CRYPT_ANSIToUnicode(pszContainer, &pContainer, -1) )
575 576 577 578
	{
		SetLastError(ERROR_NOT_ENOUGH_MEMORY);
		return FALSE;
	}
579
	if ( !CRYPT_ANSIToUnicode(pszProvider, &pProvider, -1) )
580 581
	{
		CRYPT_Free(pContainer);
582 583
		SetLastError(ERROR_NOT_ENOUGH_MEMORY);
		return FALSE;
584 585
	}

586
	ret = CryptAcquireContextW(phProv, pContainer, pProvider, dwProvType, dwFlags);
587

588 589
	CRYPT_Free(pContainer);
	CRYPT_Free(pProvider);
590 591 592 593 594 595

	return ret;
}

/******************************************************************************
 * CryptContextAddRef (ADVAPI32.@)
596 597 598 599 600 601 602 603 604 605 606 607
 *
 * 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
608 609 610
 */
BOOL WINAPI CryptContextAddRef (HCRYPTPROV hProv, DWORD *pdwReserved, DWORD dwFlags)
{
611 612
	PCRYPTPROV pProv = (PCRYPTPROV)hProv;	

613
	TRACE("(0x%lx, %p, %08x)\n", hProv, pdwReserved, dwFlags);
614 615 616 617 618 619 620

	if (!pProv)
	{
		SetLastError(NTE_BAD_UID);
		return FALSE;
	}

621 622 623 624 625 626
	if (pProv->dwMagic != MAGIC_CRYPTPROV)
	{
		SetLastError(ERROR_INVALID_PARAMETER);
		return FALSE;
	}

627 628
	pProv->refcount++;
	return TRUE;
629 630
}

Patrik Stridvall's avatar
Patrik Stridvall committed
631
/******************************************************************************
632
 * CryptReleaseContext (ADVAPI32.@)
633 634 635 636 637 638 639 640 641 642
 *
 * 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
Patrik Stridvall's avatar
Patrik Stridvall committed
643
 */
644
BOOL WINAPI CryptReleaseContext (HCRYPTPROV hProv, ULONG_PTR dwFlags)
645
{
646
	PCRYPTPROV pProv = (PCRYPTPROV)hProv;
647
	BOOL ret = TRUE;
648

649
	TRACE("(0x%lx, %08lx)\n", hProv, dwFlags);
650

651
	if (!pProv)
652
	{
653 654
		SetLastError(NTE_BAD_UID);
		return FALSE;
655
	}
656

657 658 659 660 661 662
	if (pProv->dwMagic != MAGIC_CRYPTPROV)
	{
		SetLastError(ERROR_INVALID_PARAMETER);
		return FALSE;
	}

663 664 665 666
	pProv->refcount--;
	if (pProv->refcount <= 0) 
	{
		ret = pProv->pFuncs->pCPReleaseContext(pProv->hPrivate, dwFlags);
667
		pProv->dwMagic = 0;
668
		FreeLibrary(pProv->hModule);
669
#if 0
670
		CRYPT_Free(pProv->pVTable->pContextInfo);
671
#endif
672 673 674 675 676
		CRYPT_Free(pProv->pVTable->pszProvName);
		CRYPT_Free(pProv->pVTable);
		CRYPT_Free(pProv->pFuncs);
		CRYPT_Free(pProv);
	}
677
	return ret;
678
}
679

680
/******************************************************************************
681
 * CryptGenRandom (ADVAPI32.@)
682 683 684 685 686 687 688 689 690 691 692 693 694 695
 *
 * 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.
696
 */
697
BOOL WINAPI CryptGenRandom (HCRYPTPROV hProv, DWORD dwLen, BYTE *pbBuffer)
698
{
699 700
	PCRYPTPROV prov = (PCRYPTPROV)hProv;

701
	TRACE("(0x%lx, %d, %p)\n", hProv, dwLen, pbBuffer);
702 703

	if (!hProv)
704 705 706 707
	{
		SetLastError(ERROR_INVALID_HANDLE);
		return FALSE;
	}
708

709
	if (prov->dwMagic != MAGIC_CRYPTPROV)
710 711 712 713
	{
		SetLastError(ERROR_INVALID_PARAMETER);
		return FALSE;
	}
714

715
	return prov->pFuncs->pCPGenRandom(prov->hPrivate, dwLen, pbBuffer);
716
}
717 718

/******************************************************************************
719
 * CryptCreateHash (ADVAPI32.@)
720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735
 *
 * 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.
736 737 738 739
 */
BOOL WINAPI CryptCreateHash (HCRYPTPROV hProv, ALG_ID Algid, HCRYPTKEY hKey,
		DWORD dwFlags, HCRYPTHASH *phHash)
{
740 741 742 743
	PCRYPTPROV prov = (PCRYPTPROV)hProv;
	PCRYPTKEY key = (PCRYPTKEY)hKey;
	PCRYPTHASH hash;

744
	TRACE("(0x%lx, 0x%x, 0x%lx, %08x, %p)\n", hProv, Algid, hKey, dwFlags, phHash);
745

746
	if (!prov || !phHash || prov->dwMagic != MAGIC_CRYPTPROV ||
747
		(key && key->dwMagic != MAGIC_CRYPTKEY))
748 749 750 751
	{
		SetLastError(ERROR_INVALID_PARAMETER);
		return FALSE;
	}
752
	if (dwFlags)
753 754 755 756
	{
		SetLastError(NTE_BAD_FLAGS);
		return FALSE;
	}
757
	if ( !(hash = CRYPT_Alloc(sizeof(CRYPTHASH))) )
758 759 760 761
	{
		SetLastError(ERROR_NOT_ENOUGH_MEMORY);
		return FALSE;
	}
762 763

	hash->pProvider = prov;
764
	hash->dwMagic = MAGIC_CRYPTHASH;
765 766
	if (prov->pFuncs->pCPCreateHash(prov->hPrivate, Algid,
			key ? key->hPrivate : 0, 0, &hash->hPrivate))
767 768 769 770
        {
            *phHash = (HCRYPTHASH)hash;
            return TRUE;
        }
771

772
	/* CSP error! */
773
	hash->dwMagic = 0;
774
	CRYPT_Free(hash);
775
	*phHash = 0;
776 777 778 779 780
	return FALSE;
}

/******************************************************************************
 * CryptDecrypt (ADVAPI32.@)
781 782 783 784 785 786 787 788 789 790 791 792 793 794 795
 *
 * 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
796 797 798 799
 */
BOOL WINAPI CryptDecrypt (HCRYPTKEY hKey, HCRYPTHASH hHash, BOOL Final,
		DWORD dwFlags, BYTE *pbData, DWORD *pdwDataLen)
{
800 801 802 803
	PCRYPTPROV prov;
	PCRYPTKEY key = (PCRYPTKEY)hKey;
	PCRYPTHASH hash = (PCRYPTHASH)hHash;

804
	TRACE("(0x%lx, 0x%lx, %d, %08x, %p, %p)\n", hKey, hHash, Final, dwFlags, pbData, pdwDataLen);
805

806 807 808
	if (!key || !pbData || !pdwDataLen ||
		!key->pProvider || key->dwMagic != MAGIC_CRYPTKEY ||
		key->pProvider->dwMagic != MAGIC_CRYPTPROV)
809 810 811 812
	{
		SetLastError(ERROR_INVALID_PARAMETER);
		return FALSE;
	}
813 814 815 816

	prov = key->pProvider;
	return prov->pFuncs->pCPDecrypt(prov->hPrivate, key->hPrivate, hash ? hash->hPrivate : 0,
			Final, dwFlags, pbData, pdwDataLen);
817 818 819 820
}

/******************************************************************************
 * CryptDeriveKey (ADVAPI32.@)
821 822 823 824 825 826 827 828 829 830 831 832 833
 *
 * 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
834 835 836 837
 */
BOOL WINAPI CryptDeriveKey (HCRYPTPROV hProv, ALG_ID Algid, HCRYPTHASH hBaseData,
		DWORD dwFlags, HCRYPTKEY *phKey)
{
838 839 840 841
	PCRYPTPROV prov = (PCRYPTPROV)hProv;
	PCRYPTHASH hash = (PCRYPTHASH)hBaseData;
	PCRYPTKEY key;

842
	TRACE("(0x%lx, 0x%08x, 0x%lx, 0x%08x, %p)\n", hProv, Algid, hBaseData, dwFlags, phKey);
843 844

	if (!prov || !hash)
845 846 847 848
	{
		SetLastError(ERROR_INVALID_HANDLE);
		return FALSE;
	}
849
	if (!phKey || prov->dwMagic != MAGIC_CRYPTPROV || hash->dwMagic != MAGIC_CRYPTHASH)
850 851 852 853
	{
		SetLastError(ERROR_INVALID_PARAMETER);
		return FALSE;
	}
854
	if ( !(key = CRYPT_Alloc(sizeof(CRYPTKEY))) )
855 856 857 858
	{
		SetLastError(ERROR_NOT_ENOUGH_MEMORY);
		return FALSE;
	}
859 860

	key->pProvider = prov;
861
	key->dwMagic = MAGIC_CRYPTKEY;
862
	if (prov->pFuncs->pCPDeriveKey(prov->hPrivate, Algid, hash->hPrivate, dwFlags, &key->hPrivate))
863 864 865 866
        {
            *phKey = (HCRYPTKEY)key;
            return TRUE;
        }
867

868
	/* CSP error! */
869
	key->dwMagic = 0;
870
	CRYPT_Free(key);
871
	*phKey = 0;
872 873 874 875 876
	return FALSE;
}

/******************************************************************************
 * CryptDestroyHash (ADVAPI32.@)
877 878 879 880 881 882 883 884 885
 *
 * Destroys the hash object referenced by hHash.
 *
 * PARAMS
 *  hHash [I] Handle of the hash object to be destroyed.
 *
 * RETURNS
 *  Success: TRUE
 *  Failure: FALSE
886 887 888
 */
BOOL WINAPI CryptDestroyHash (HCRYPTHASH hHash)
{
889 890 891 892 893 894 895
	PCRYPTHASH hash = (PCRYPTHASH)hHash;
	PCRYPTPROV prov;
	BOOL ret;

	TRACE("(0x%lx)\n", hHash);

	if (!hash)
896 897 898 899
	{
		SetLastError(ERROR_INVALID_HANDLE);
		return FALSE;
	}
900

901 902
	if (!hash->pProvider || hash->dwMagic != MAGIC_CRYPTHASH ||
		hash->pProvider->dwMagic != MAGIC_CRYPTPROV)
903 904 905 906 907
	{
		SetLastError(ERROR_INVALID_PARAMETER);
		return FALSE;
	}

908 909
	prov = hash->pProvider;
	ret = prov->pFuncs->pCPDestroyHash(prov->hPrivate, hash->hPrivate);
910
	hash->dwMagic = 0;
911 912
	CRYPT_Free(hash);
	return ret;
913 914 915
}

/******************************************************************************
916 917 918 919 920 921 922 923 924 925
 * CryptDestroyKey (ADVAPI32.@)
 *
 * Releases the handle referenced by hKey.
 *
 * PARAMS
 *  hKey [I] Handle of the key to be destroyed.
 *
 * RETURNS
 *  Success: TRUE
 *  Failure: FALSE
926 927 928
 */
BOOL WINAPI CryptDestroyKey (HCRYPTKEY hKey)
{
929 930 931 932 933 934 935
	PCRYPTKEY key = (PCRYPTKEY)hKey;
	PCRYPTPROV prov;
	BOOL ret;

	TRACE("(0x%lx)\n", hKey);

	if (!key)
936 937 938 939
	{
		SetLastError(ERROR_INVALID_HANDLE);
		return FALSE;
	}
940

941 942
	if (!key->pProvider || key->dwMagic != MAGIC_CRYPTKEY ||
		key->pProvider->dwMagic != MAGIC_CRYPTPROV)
943 944 945 946
	{
		SetLastError(ERROR_INVALID_PARAMETER);
		return FALSE;
	}
947

948 949
	prov = key->pProvider;
	ret = prov->pFuncs->pCPDestroyKey(prov->hPrivate, key->hPrivate);
950
	key->dwMagic = 0;
951 952
	CRYPT_Free(key);
	return ret;
953 954 955 956
}

/******************************************************************************
 * CryptDuplicateHash (ADVAPI32.@)
957 958 959 960 961 962 963 964 965 966 967 968
 *
 * 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
969 970 971 972
 */
BOOL WINAPI CryptDuplicateHash (HCRYPTHASH hHash, DWORD *pdwReserved,
		DWORD dwFlags, HCRYPTHASH *phHash)
{
973 974 975
	PCRYPTPROV prov;
	PCRYPTHASH orghash, newhash;

976
	TRACE("(0x%lx, %p, %08x, %p)\n", hHash, pdwReserved, dwFlags, phHash);
977 978

	orghash = (PCRYPTHASH)hHash;
979 980
	if (!orghash || pdwReserved || !phHash || !orghash->pProvider ||
		orghash->dwMagic != MAGIC_CRYPTHASH || orghash->pProvider->dwMagic != MAGIC_CRYPTPROV)
981
	{
982 983
		SetLastError(ERROR_INVALID_PARAMETER);
		return FALSE;
984
	}
985 986 987

	prov = orghash->pProvider;
	if (!prov->pFuncs->pCPDuplicateHash)
988 989 990 991
	{
		SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
		return FALSE;
	}
992 993

	if ( !(newhash = CRYPT_Alloc(sizeof(CRYPTHASH))) )
994 995 996 997
	{
		SetLastError(ERROR_NOT_ENOUGH_MEMORY);
		return FALSE;
	}
998 999

	newhash->pProvider = prov;
1000
	newhash->dwMagic = MAGIC_CRYPTHASH;
1001 1002 1003 1004 1005
	if (prov->pFuncs->pCPDuplicateHash(prov->hPrivate, orghash->hPrivate, pdwReserved, dwFlags, &newhash->hPrivate))
	{
		*phHash = (HCRYPTHASH)newhash;
		return TRUE;
	}
1006
	newhash->dwMagic = 0;
1007
	CRYPT_Free(newhash);
1008 1009 1010 1011 1012
	return FALSE;
}

/******************************************************************************
 * CryptDuplicateKey (ADVAPI32.@)
1013 1014 1015 1016 1017 1018 1019 1020 1021 1022 1023 1024
 *
 * 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
1025 1026 1027
 */
BOOL WINAPI CryptDuplicateKey (HCRYPTKEY hKey, DWORD *pdwReserved, DWORD dwFlags, HCRYPTKEY *phKey)
{
1028 1029 1030
	PCRYPTPROV prov;
	PCRYPTKEY orgkey, newkey;

1031
	TRACE("(0x%lx, %p, %08x, %p)\n", hKey, pdwReserved, dwFlags, phKey);
1032 1033

	orgkey = (PCRYPTKEY)hKey;
1034 1035
	if (!orgkey || pdwReserved || !phKey || !orgkey->pProvider ||
		orgkey->dwMagic != MAGIC_CRYPTKEY ||
1036 1037
		orgkey->pProvider->dwMagic != MAGIC_CRYPTPROV)
	{
1038 1039
		SetLastError(ERROR_INVALID_PARAMETER);
		return FALSE;
1040
	}
1041 1042 1043

	prov = orgkey->pProvider;
	if (!prov->pFuncs->pCPDuplicateKey)
1044 1045 1046 1047
	{
		SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
		return FALSE;
	}
1048 1049

	if ( !(newkey = CRYPT_Alloc(sizeof(CRYPTKEY))) )
1050 1051 1052 1053
	{
		SetLastError(ERROR_NOT_ENOUGH_MEMORY);
		return FALSE;
	}
1054 1055

	newkey->pProvider = prov;
1056
	newkey->dwMagic = MAGIC_CRYPTKEY;
1057 1058 1059 1060 1061
	if (prov->pFuncs->pCPDuplicateKey(prov->hPrivate, orgkey->hPrivate, pdwReserved, dwFlags, &newkey->hPrivate))
	{
		*phKey = (HCRYPTKEY)newkey;
		return TRUE;
	}
1062
	newkey->dwMagic = 0;
1063
	CRYPT_Free(newkey);
1064 1065 1066 1067 1068
	return FALSE;
}

/******************************************************************************
 * CryptEncrypt (ADVAPI32.@)
1069 1070 1071 1072
 *
 * Encrypts data.
 *
 * PARAMS
Lei Zhang's avatar
Lei Zhang committed
1073
 *  hKey       [I] Handle to the encryption key.
1074 1075 1076 1077 1078 1079 1080 1081 1082 1083 1084 1085 1086 1087 1088
 *  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.
1089 1090 1091 1092
 */
BOOL WINAPI CryptEncrypt (HCRYPTKEY hKey, HCRYPTHASH hHash, BOOL Final,
		DWORD dwFlags, BYTE *pbData, DWORD *pdwDataLen, DWORD dwBufLen)
{
1093 1094 1095 1096
	PCRYPTPROV prov;
	PCRYPTKEY key = (PCRYPTKEY)hKey;
	PCRYPTHASH hash = (PCRYPTHASH)hHash;

1097
	TRACE("(0x%lx, 0x%lx, %d, %08x, %p, %p, %d)\n", hKey, hHash, Final, dwFlags, pbData, pdwDataLen, dwBufLen);
1098

1099 1100
	if (!key || !pdwDataLen || !key->pProvider ||
		key->dwMagic != MAGIC_CRYPTKEY || key->pProvider->dwMagic != MAGIC_CRYPTPROV)
1101 1102 1103 1104
	{
		SetLastError(ERROR_INVALID_PARAMETER);
		return FALSE;
	}
1105 1106 1107 1108

	prov = key->pProvider;
	return prov->pFuncs->pCPEncrypt(prov->hPrivate, key->hPrivate, hash ? hash->hPrivate : 0,
			Final, dwFlags, pbData, pdwDataLen, dwBufLen);
1109 1110 1111
}

/******************************************************************************
1112
 * CryptEnumProvidersW (ADVAPI32.@)
1113
 *
Lei Zhang's avatar
Lei Zhang committed
1114
 * Returns the next available CSP.
1115 1116 1117 1118 1119 1120 1121 1122
 *
 * 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
1123
 *                    of bytes stored in the buffer on return.
1124 1125 1126 1127 1128 1129
 *
 *  RETURNS
 *   Success: TRUE
 *   Failure: FALSE
 *
 *  NOTES
1130
 *   If pszProvName is NULL, CryptEnumProvidersW sets the size of the name
1131
 *   for memory allocation purposes.
1132
 */
1133 1134
BOOL WINAPI CryptEnumProvidersW (DWORD dwIndex, DWORD *pdwReserved,
		DWORD dwFlags, DWORD *pdwProvType, LPWSTR pszProvName, DWORD *pcbProvName)
1135
{
1136
	HKEY hKey;
1137 1138 1139 1140 1141 1142 1143 1144
	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};
1145
	BOOL ret;
1146

1147
	TRACE("(%d, %p, %d, %p, %p, %p)\n", dwIndex, pdwReserved, dwFlags,
1148
			pdwProvType, pszProvName, pcbProvName);
1149

1150 1151 1152 1153 1154 1155 1156 1157 1158 1159
	if (pdwReserved || !pcbProvName)
	{
		SetLastError(ERROR_INVALID_PARAMETER);
		return FALSE;
	}
	if (dwFlags)
	{
		SetLastError(NTE_BAD_FLAGS);
		return FALSE;
	}
1160

1161
	if (RegOpenKeyW(HKEY_LOCAL_MACHINE, providerW, &hKey))
1162 1163 1164 1165
	{
		SetLastError(NTE_FAIL);
		return FALSE;
	}
1166

1167
	ret = TRUE;
1168 1169 1170
	if (!pszProvName)
	{
		DWORD numkeys;
1171
		WCHAR *provNameW;
1172
		
1173 1174
		RegQueryInfoKeyW(hKey, NULL, NULL, NULL, &numkeys, pcbProvName,
				 NULL, NULL, NULL, NULL, NULL, NULL);
1175
		
1176
		if (!(provNameW = CRYPT_Alloc(*pcbProvName * sizeof(WCHAR))))
1177 1178
		{
			SetLastError(ERROR_NOT_ENOUGH_MEMORY);
1179
			RegCloseKey(hKey);
1180 1181 1182
			return FALSE;
		}

1183
		RegEnumKeyExW(hKey, dwIndex, provNameW, pcbProvName, NULL, NULL, NULL, NULL);
1184
		CRYPT_Free(provNameW);
1185
		(*pcbProvName)++;
1186
		*pcbProvName *= sizeof(WCHAR);
1187

1188
		if (dwIndex >= numkeys)
1189 1190
		{
			SetLastError(ERROR_NO_MORE_ITEMS);
1191
			ret = FALSE;
1192
		}
1193 1194
	} else {
		DWORD size = sizeof(DWORD);
1195
		DWORD result;
1196
		HKEY subkey;
1197 1198 1199
		
		result = RegEnumKeyW(hKey, dwIndex, pszProvName, *pcbProvName / sizeof(WCHAR));
		if (result)
1200 1201
		{
			SetLastError(result);
1202
			RegCloseKey(hKey);
1203 1204
			return FALSE;
		}
1205
		if (RegOpenKeyW(hKey, pszProvName, &subkey))
1206 1207
		{
			RegCloseKey(hKey);
1208
			return FALSE;
1209 1210
		}

1211
		if (RegQueryValueExW(subkey, typeW, NULL, NULL, (BYTE*)pdwProvType, &size))
1212 1213
			ret = FALSE;

1214 1215 1216
		RegCloseKey(subkey);
	}
	RegCloseKey(hKey);
1217
	return ret;
1218 1219 1220
}

/******************************************************************************
1221
 * CryptEnumProvidersA (ADVAPI32.@)
1222
 *
1223
 * See CryptEnumProvidersW.
1224
 */
1225 1226
BOOL WINAPI CryptEnumProvidersA (DWORD dwIndex, DWORD *pdwReserved,
		DWORD dwFlags, DWORD *pdwProvType, LPSTR pszProvName, DWORD *pcbProvName)
1227
{
1228
	PWSTR str = NULL;
1229
	DWORD bufsize;
1230
	BOOL ret;
1231

1232
	TRACE("(%d, %p, %08x, %p, %p, %p)\n", dwIndex, pdwReserved, dwFlags,
1233
			pdwProvType, pszProvName, pcbProvName);
1234

1235
	if(!CryptEnumProvidersW(dwIndex, pdwReserved, dwFlags, pdwProvType, NULL, &bufsize))
1236
		return FALSE;
1237
	if ( pszProvName && !(str = CRYPT_Alloc(bufsize)) )
1238 1239 1240 1241
	{
		SetLastError(ERROR_NOT_ENOUGH_MEMORY);
		return FALSE;
	}
1242
	ret = CryptEnumProvidersW(dwIndex, pdwReserved, dwFlags, pdwProvType, str, &bufsize);
1243
	if (str)
1244
		CRYPT_UnicodeToANSI(str, &pszProvName, *pcbProvName);
1245
	*pcbProvName = bufsize / sizeof(WCHAR);  /* FIXME: not correct */
1246 1247
	if (str)
	{
1248
		CRYPT_Free(str);
1249
		if (GetLastError() == ERROR_INSUFFICIENT_BUFFER)
1250 1251 1252 1253
		{
			SetLastError(ERROR_MORE_DATA);
			return FALSE;
		}
1254 1255
	}
	return ret;
1256 1257 1258
}

/******************************************************************************
1259
 * CryptEnumProviderTypesW (ADVAPI32.@)
1260 1261 1262 1263 1264 1265 1266 1267 1268 1269
 *
 * 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
1270
 *                    of bytes stored in the buffer on return.
1271 1272 1273 1274 1275 1276
 *
 *  RETURNS
 *   Success: TRUE
 *   Failure: FALSE
 *
 *  NOTES
1277
 *   If pszTypeName is NULL, CryptEnumProviderTypesW sets the size of the name
1278
 *   for memory allocation purposes.
1279
 */
1280 1281
BOOL WINAPI CryptEnumProviderTypesW (DWORD dwIndex, DWORD *pdwReserved,
		DWORD dwFlags, DWORD *pdwProvType, LPWSTR pszTypeName, DWORD *pcbTypeName)
1282
{
1283
	HKEY hKey, hSubkey;
1284
	DWORD keylen, numkeys, dwType;
1285
	PWSTR keyname, ch;
1286
	DWORD result;
1287 1288 1289 1290 1291 1292 1293 1294
	static const WCHAR KEYSTR[] = {
                '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',' ','T','y','p','e','s',0
	};
	static const WCHAR typenameW[] = {'T','y','p','e','N','a','m','e',0};
1295

1296
	TRACE("(%d, %p, %08x, %p, %p, %p)\n", dwIndex, pdwReserved,
1297 1298 1299
		dwFlags, pdwProvType, pszTypeName, pcbTypeName);

	if (pdwReserved || !pdwProvType || !pcbTypeName)
1300 1301 1302 1303 1304 1305 1306 1307 1308
	{
		SetLastError(ERROR_INVALID_PARAMETER);
		return FALSE;
	}
	if (dwFlags)
	{
		SetLastError(NTE_BAD_FLAGS);
		return FALSE;
	}
1309

1310
	if (RegOpenKeyW(HKEY_LOCAL_MACHINE, KEYSTR, &hKey))
1311 1312
		return FALSE;

1313
	RegQueryInfoKeyW(hKey, NULL, NULL, NULL, &numkeys, &keylen, NULL, NULL, NULL, NULL, NULL, NULL);
1314
	if (dwIndex >= numkeys)
1315 1316
	{
		SetLastError(ERROR_NO_MORE_ITEMS);
1317
		RegCloseKey(hKey);
1318 1319
		return FALSE;
	}
1320
	keylen++;
1321
	if ( !(keyname = CRYPT_Alloc(keylen*sizeof(WCHAR))) )
1322 1323
	{
		SetLastError(ERROR_NOT_ENOUGH_MEMORY);
1324
		RegCloseKey(hKey);
1325 1326
		return FALSE;
	}
1327
	if ( RegEnumKeyW(hKey, dwIndex, keyname, keylen) ) {
1328
                CRYPT_Free(keyname);
1329
		RegCloseKey(hKey);
1330
		return FALSE;
1331
        }
1332
	RegOpenKeyW(hKey, keyname, &hSubkey);
1333 1334
	RegCloseKey(hKey);

1335
	ch = keyname + strlenW(keyname);
1336
	/* Convert "Type 000" to 0, etc/ */
1337 1338 1339 1340
	*pdwProvType = *(--ch) - '0';
	*pdwProvType += (*(--ch) - '0') * 10;
	*pdwProvType += (*(--ch) - '0') * 100;
	CRYPT_Free(keyname);
1341
	
1342
	result = RegQueryValueExW(hSubkey, typenameW, NULL, &dwType, (LPBYTE)pszTypeName, pcbTypeName);
1343
	if (result)
1344 1345
	{
		SetLastError(result);
1346
		RegCloseKey(hSubkey);
1347 1348
		return FALSE;
	}
1349

1350 1351
	RegCloseKey(hSubkey);
	return TRUE;
1352 1353 1354
}

/******************************************************************************
1355
 * CryptEnumProviderTypesA (ADVAPI32.@)
1356
 *
1357
 * See CryptEnumProviderTypesW.
1358
 */
1359 1360
BOOL WINAPI CryptEnumProviderTypesA (DWORD dwIndex, DWORD *pdwReserved,
		DWORD dwFlags, DWORD *pdwProvType, LPSTR pszTypeName, DWORD *pcbTypeName)
1361
{
1362
	PWSTR str = NULL;
1363
	DWORD bufsize;
1364 1365
	BOOL ret;

1366
	TRACE("(%d, %p, %08x, %p, %p, %p)\n", dwIndex, pdwReserved, dwFlags,
1367
			pdwProvType, pszTypeName, pcbTypeName);
1368

1369
	if(!CryptEnumProviderTypesW(dwIndex, pdwReserved, dwFlags, pdwProvType, NULL, &bufsize))
1370
		return FALSE;
1371
	if ( pszTypeName && !(str = CRYPT_Alloc(bufsize)) )
1372 1373 1374 1375
	{
		SetLastError(ERROR_NOT_ENOUGH_MEMORY);
		return FALSE;
	}
1376
	ret = CryptEnumProviderTypesW(dwIndex, pdwReserved, dwFlags, pdwProvType, str, &bufsize);
1377 1378
	if (str)
		CRYPT_UnicodeToANSI(str, &pszTypeName, *pcbTypeName);
1379
	*pcbTypeName = bufsize / sizeof(WCHAR);
1380 1381 1382
	if (str)
	{
		CRYPT_Free(str);
1383
		if (GetLastError() == ERROR_INSUFFICIENT_BUFFER)
1384 1385 1386 1387
		{
			SetLastError(ERROR_MORE_DATA);
			return FALSE;
		}
1388 1389
	}
	return ret;
1390 1391 1392 1393
}

/******************************************************************************
 * CryptExportKey (ADVAPI32.@)
1394 1395 1396 1397 1398 1399 1400 1401 1402 1403 1404 1405 1406 1407 1408 1409 1410 1411
 * 
 * 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.
1412 1413 1414 1415
 */
BOOL WINAPI CryptExportKey (HCRYPTKEY hKey, HCRYPTKEY hExpKey, DWORD dwBlobType,
		DWORD dwFlags, BYTE *pbData, DWORD *pdwDataLen)
{
1416 1417 1418
	PCRYPTPROV prov;
	PCRYPTKEY key = (PCRYPTKEY)hKey, expkey = (PCRYPTKEY)hExpKey;

1419
	TRACE("(0x%lx, 0x%lx, %d, %08x, %p, %p)\n", hKey, hExpKey, dwBlobType, dwFlags, pbData, pdwDataLen);
1420

1421 1422
	if (!key || !pdwDataLen || !key->pProvider ||
		key->dwMagic != MAGIC_CRYPTKEY || key->pProvider->dwMagic != MAGIC_CRYPTPROV)
1423 1424 1425 1426
	{
		SetLastError(ERROR_INVALID_PARAMETER);
		return FALSE;
	}
1427 1428 1429 1430

	prov = key->pProvider;
	return prov->pFuncs->pCPExportKey(prov->hPrivate, key->hPrivate, expkey ? expkey->hPrivate : 0,
			dwBlobType, dwFlags, pbData, pdwDataLen);
1431 1432 1433 1434
}

/******************************************************************************
 * CryptGenKey (ADVAPI32.@)
1435 1436 1437 1438 1439 1440 1441 1442 1443 1444 1445 1446
 *
 * 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
1447 1448 1449
 */
BOOL WINAPI CryptGenKey (HCRYPTPROV hProv, ALG_ID Algid, DWORD dwFlags, HCRYPTKEY *phKey)
{
1450 1451 1452
	PCRYPTPROV prov = (PCRYPTPROV)hProv;
	PCRYPTKEY key;

1453
	TRACE("(0x%lx, %d, %08x, %p)\n", hProv, Algid, dwFlags, phKey);
1454

1455
	if (!phKey || !prov || prov->dwMagic != MAGIC_CRYPTPROV)
1456 1457 1458 1459
	{
		SetLastError(ERROR_INVALID_PARAMETER);
		return FALSE;
	}
1460
	if ( !(key = CRYPT_Alloc(sizeof(CRYPTKEY))) )
1461 1462 1463 1464
	{
		SetLastError(ERROR_NOT_ENOUGH_MEMORY);
		return FALSE;
	}
1465 1466

	key->pProvider = prov;
1467
	key->dwMagic = MAGIC_CRYPTKEY;
1468
	if (prov->pFuncs->pCPGenKey(prov->hPrivate, Algid, dwFlags, &key->hPrivate))
1469 1470 1471 1472
        {
            *phKey = (HCRYPTKEY)key;
            return TRUE;
        }
1473

1474
	/* CSP error! */
1475
	key->dwMagic = 0;
1476
	CRYPT_Free(key);
1477 1478 1479 1480
	return FALSE;
}

/******************************************************************************
1481
 * CryptGetDefaultProviderW (ADVAPI32.@)
1482 1483 1484 1485 1486 1487 1488 1489 1490 1491 1492 1493 1494 1495 1496 1497 1498
 *
 * 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.
1499
 */
1500 1501
BOOL WINAPI CryptGetDefaultProviderW (DWORD dwProvType, DWORD *pdwReserved,
		DWORD dwFlags, LPWSTR pszProvName, DWORD *pcbProvName)
1502
{
1503
	HKEY hKey;
1504
	PWSTR keyname;
1505
	DWORD result;
1506
	static const WCHAR nameW[] = {'N','a','m','e',0};
1507 1508

	if (pdwReserved || !pcbProvName)
1509 1510 1511 1512
	{
		SetLastError(ERROR_INVALID_PARAMETER);
		return FALSE;
	}
1513
	if (dwFlags & ~(CRYPT_USER_DEFAULT | CRYPT_MACHINE_DEFAULT))
1514 1515 1516 1517
	{
		SetLastError(NTE_BAD_FLAGS);
		return FALSE;
	}
1518
	if (dwProvType > 999)
1519 1520 1521 1522
	{
		SetLastError(NTE_BAD_PROV_TYPE);
		return FALSE;
	}
1523
	if ( !(keyname = CRYPT_GetTypeKeyName(dwProvType, dwFlags & CRYPT_USER_DEFAULT)) )
1524 1525 1526 1527
	{
		SetLastError(ERROR_NOT_ENOUGH_MEMORY);
		return FALSE;
	}
1528
	if (RegOpenKeyW((dwFlags & CRYPT_USER_DEFAULT) ?  HKEY_CURRENT_USER : HKEY_LOCAL_MACHINE ,keyname, &hKey))
1529 1530
	{
		CRYPT_Free(keyname);
1531 1532
		SetLastError(NTE_PROV_TYPE_NOT_DEF);
		return FALSE;
1533 1534
	}
	CRYPT_Free(keyname);
1535
	
1536
	result = RegQueryValueExW(hKey, nameW, NULL, NULL, (LPBYTE)pszProvName, pcbProvName); 
1537 1538
	RegCloseKey(hKey);

1539
	if (result)
1540
	{
1541
		if (result != ERROR_MORE_DATA)
1542
			SetLastError(NTE_PROV_TYPE_ENTRY_BAD);
1543 1544 1545
		else
			SetLastError(result);
		
1546 1547
		return FALSE;
	}
1548
	
1549
	return TRUE;
1550 1551 1552
}

/******************************************************************************
1553
 * CryptGetDefaultProviderA (ADVAPI32.@)
1554
 *
1555
 * See CryptGetDefaultProviderW.
1556
 */
1557 1558
BOOL WINAPI CryptGetDefaultProviderA (DWORD dwProvType, DWORD *pdwReserved,
		DWORD dwFlags, LPSTR pszProvName, DWORD *pcbProvName)
1559
{
1560
	PWSTR str = NULL;
1561
	DWORD bufsize;
1562
	BOOL ret;
1563

1564
	TRACE("(%d, %p, %08x, %p, %p)\n", dwProvType, pdwReserved, dwFlags, pszProvName, pcbProvName);
1565

1566 1567
	CryptGetDefaultProviderW(dwProvType, pdwReserved, dwFlags, NULL, &bufsize);
	if ( pszProvName && !(str = CRYPT_Alloc(bufsize)) )
1568 1569 1570 1571
	{
		SetLastError(ERROR_NOT_ENOUGH_MEMORY);
		return FALSE;
	}
1572
	ret = CryptGetDefaultProviderW(dwProvType, pdwReserved, dwFlags, str, &bufsize);
1573 1574
	if (str)
		CRYPT_UnicodeToANSI(str, &pszProvName, *pcbProvName);
1575
	*pcbProvName = bufsize / sizeof(WCHAR);
1576 1577 1578
	if (str)
	{
		CRYPT_Free(str);
1579
		if (GetLastError() == ERROR_INSUFFICIENT_BUFFER)
1580 1581 1582 1583
		{
			SetLastError(ERROR_MORE_DATA);
			return FALSE;
		}
1584 1585
	}
	return ret;
1586
}
1587

1588 1589
/******************************************************************************
 * CryptGetHashParam (ADVAPI32.@)
1590 1591 1592 1593 1594 1595 1596 1597 1598 1599 1600 1601 1602 1603 1604 1605
 *
 * 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.
1606 1607 1608 1609
 */
BOOL WINAPI CryptGetHashParam (HCRYPTHASH hHash, DWORD dwParam, BYTE *pbData,
		DWORD *pdwDataLen, DWORD dwFlags)
{
1610 1611 1612
	PCRYPTPROV prov;
	PCRYPTHASH hash = (PCRYPTHASH)hHash;

1613
	TRACE("(0x%lx, %d, %p, %p, %08x)\n", hHash, dwParam, pbData, pdwDataLen, dwFlags);
1614

1615 1616
	if (!hash || !pdwDataLen || !hash->pProvider ||
		hash->dwMagic != MAGIC_CRYPTHASH || hash->pProvider->dwMagic != MAGIC_CRYPTPROV)
1617 1618 1619 1620
	{
		SetLastError(ERROR_INVALID_PARAMETER);
		return FALSE;
	}
1621 1622 1623 1624

	prov = hash->pProvider;
	return prov->pFuncs->pCPGetHashParam(prov->hPrivate, hash->hPrivate, dwParam,
			pbData, pdwDataLen, dwFlags);
1625
}
1626

1627 1628
/******************************************************************************
 * CryptGetKeyParam (ADVAPI32.@)
1629 1630 1631 1632 1633 1634 1635 1636 1637 1638 1639 1640 1641 1642 1643 1644
 *
 * 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.
1645 1646 1647 1648
 */
BOOL WINAPI CryptGetKeyParam (HCRYPTKEY hKey, DWORD dwParam, BYTE *pbData,
		DWORD *pdwDataLen, DWORD dwFlags)
{
1649 1650 1651
	PCRYPTPROV prov;
	PCRYPTKEY key = (PCRYPTKEY)hKey;

1652
	TRACE("(0x%lx, %d, %p, %p, %08x)\n", hKey, dwParam, pbData, pdwDataLen, dwFlags);
1653

1654 1655
	if (!key || !pdwDataLen || !key->pProvider ||
		key->dwMagic != MAGIC_CRYPTKEY || key->pProvider->dwMagic != MAGIC_CRYPTPROV)
1656 1657 1658 1659
	{
		SetLastError(ERROR_INVALID_PARAMETER);
		return FALSE;
	}
1660 1661 1662 1663

	prov = key->pProvider;
	return prov->pFuncs->pCPGetKeyParam(prov->hPrivate, key->hPrivate, dwParam,
			pbData, pdwDataLen, dwFlags);
1664
}
1665

1666 1667
/******************************************************************************
 * CryptGetProvParam (ADVAPI32.@)
1668 1669 1670 1671 1672 1673 1674 1675 1676 1677 1678 1679 1680 1681 1682 1683
 *
 * 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.
1684 1685 1686 1687
 */
BOOL WINAPI CryptGetProvParam (HCRYPTPROV hProv, DWORD dwParam, BYTE *pbData,
		DWORD *pdwDataLen, DWORD dwFlags)
{
1688 1689
	PCRYPTPROV prov = (PCRYPTPROV)hProv;

1690
	TRACE("(0x%lx, %d, %p, %p, %08x)\n", hProv, dwParam, pbData, pdwDataLen, dwFlags);
1691

1692
	if (!prov || prov->dwMagic != MAGIC_CRYPTPROV)
1693 1694 1695 1696
	{
		SetLastError(ERROR_INVALID_PARAMETER);
		return FALSE;
	}
1697

1698
	return prov->pFuncs->pCPGetProvParam(prov->hPrivate, dwParam, pbData, pdwDataLen, dwFlags);
1699
}
1700

1701 1702
/******************************************************************************
 * CryptGetUserKey (ADVAPI32.@)
1703 1704 1705 1706 1707 1708 1709 1710 1711 1712 1713
 *
 * 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
1714 1715 1716
 */
BOOL WINAPI CryptGetUserKey (HCRYPTPROV hProv, DWORD dwKeySpec, HCRYPTKEY *phUserKey)
{
1717 1718 1719
	PCRYPTPROV prov = (PCRYPTPROV)hProv;
	PCRYPTKEY key;

1720
	TRACE("(0x%lx, %d, %p)\n", hProv, dwKeySpec, phUserKey);
1721 1722

	if (!prov)
1723 1724 1725 1726
	{
		SetLastError(ERROR_INVALID_HANDLE);
		return FALSE;
	}
1727
	if (!phUserKey || prov->dwMagic != MAGIC_CRYPTPROV)
1728 1729 1730 1731
	{
		SetLastError(ERROR_INVALID_PARAMETER);
		return FALSE;
	}
1732
	if ( !(key = CRYPT_Alloc(sizeof(CRYPTKEY))) )
1733 1734 1735 1736
	{
		SetLastError(ERROR_NOT_ENOUGH_MEMORY);
		return FALSE;
	}
1737 1738

	key->pProvider = prov;
1739
	key->dwMagic = MAGIC_CRYPTKEY;
1740
	if (prov->pFuncs->pCPGetUserKey(prov->hPrivate, dwKeySpec, &key->hPrivate))
1741 1742 1743 1744
        {
            *phUserKey = (HCRYPTKEY)key;
            return TRUE;
        }
1745

1746
	/* CSP Error */
1747
	key->dwMagic = 0;
1748
	CRYPT_Free(key);
1749
	*phUserKey = 0;
1750
	return FALSE;
1751 1752
}

1753 1754
/******************************************************************************
 * CryptHashData (ADVAPI32.@)
1755 1756 1757 1758 1759 1760 1761 1762 1763 1764 1765 1766
 *
 * 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
1767
 */
1768
BOOL WINAPI CryptHashData (HCRYPTHASH hHash, const BYTE *pbData, DWORD dwDataLen, DWORD dwFlags)
1769
{
1770 1771 1772
	PCRYPTHASH hash = (PCRYPTHASH)hHash;
	PCRYPTPROV prov;

1773
	TRACE("(0x%lx, %p, %d, %08x)\n", hHash, pbData, dwDataLen, dwFlags);
1774 1775

	if (!hash)
1776 1777 1778 1779
	{
		SetLastError(ERROR_INVALID_HANDLE);
		return FALSE;
	}
1780 1781
	if (!hash->pProvider || hash->dwMagic != MAGIC_CRYPTHASH ||
		hash->pProvider->dwMagic != MAGIC_CRYPTPROV)
1782 1783 1784 1785
	{
		SetLastError(ERROR_INVALID_PARAMETER);
		return FALSE;
	}
1786 1787 1788

	prov = hash->pProvider;
	return prov->pFuncs->pCPHashData(prov->hPrivate, hash->hPrivate, pbData, dwDataLen, dwFlags);
1789 1790 1791 1792
}

/******************************************************************************
 * CryptHashSessionKey (ADVAPI32.@)
1793
 *
1794 1795
 * Compute the cryptographic hash of a session key object.
 *
1796 1797 1798 1799 1800 1801 1802 1803
 * 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
1804 1805 1806
 */
BOOL WINAPI CryptHashSessionKey (HCRYPTHASH hHash, HCRYPTKEY hKey, DWORD dwFlags)
{
1807 1808 1809 1810
	PCRYPTHASH hash = (PCRYPTHASH)hHash;
	PCRYPTKEY key = (PCRYPTKEY)hKey;
	PCRYPTPROV prov;

1811
	TRACE("(0x%lx, 0x%lx, %08x)\n", hHash, hKey, dwFlags);
1812 1813

	if (!hash || !key)
1814 1815 1816 1817
	{
		SetLastError(ERROR_INVALID_HANDLE);
		return FALSE;
	}
1818

1819 1820
	if (!hash->pProvider || hash->dwMagic != MAGIC_CRYPTHASH ||
		hash->pProvider->dwMagic != MAGIC_CRYPTPROV || key->dwMagic != MAGIC_CRYPTKEY)
1821 1822 1823 1824
	{
		SetLastError(ERROR_INVALID_PARAMETER);
		return FALSE;
	}
1825

1826 1827
	prov = hash->pProvider;
	return prov->pFuncs->pCPHashSessionKey(prov->hPrivate, hash->hPrivate, key->hPrivate, dwFlags);
1828 1829 1830 1831
}

/******************************************************************************
 * CryptImportKey (ADVAPI32.@)
1832
 *
1833 1834
 * Transfer a cryptographic key from a key BLOB into a cryptographic service provider (CSP).
 *
1835 1836 1837 1838 1839 1840 1841 1842 1843 1844 1845
 * 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
1846
 */
1847
BOOL WINAPI CryptImportKey (HCRYPTPROV hProv, const BYTE *pbData, DWORD dwDataLen,
1848 1849
		HCRYPTKEY hPubKey, DWORD dwFlags, HCRYPTKEY *phKey)
{
1850 1851
	PCRYPTPROV prov = (PCRYPTPROV)hProv;
	PCRYPTKEY pubkey = (PCRYPTKEY)hPubKey, importkey;
1852

1853
	TRACE("(0x%lx, %p, %d, 0x%lx, %08x, %p)\n", hProv, pbData, dwDataLen, hPubKey, dwFlags, phKey);
1854

1855 1856 1857
	if (!prov || !pbData || !dwDataLen || !phKey ||
		prov->dwMagic != MAGIC_CRYPTPROV ||
		(pubkey && pubkey->dwMagic != MAGIC_CRYPTKEY))
1858 1859 1860 1861
	{
		SetLastError(ERROR_INVALID_PARAMETER);
		return FALSE;
	}
1862 1863

	if ( !(importkey = CRYPT_Alloc(sizeof(CRYPTKEY))) )
1864 1865 1866 1867
	{
		SetLastError(ERROR_NOT_ENOUGH_MEMORY);
		return FALSE;
	}
1868 1869

	importkey->pProvider = prov;
1870
	importkey->dwMagic = MAGIC_CRYPTKEY;
1871 1872 1873 1874 1875 1876 1877
	if (prov->pFuncs->pCPImportKey(prov->hPrivate, pbData, dwDataLen,
			pubkey ? pubkey->hPrivate : 0, dwFlags, &importkey->hPrivate))
	{
		*phKey = (HCRYPTKEY)importkey;
		return TRUE;
	}

1878
	importkey->dwMagic = 0;
1879
	CRYPT_Free(importkey);
1880 1881 1882 1883
	return FALSE;
}

/******************************************************************************
1884
 * CryptSignHashW (ADVAPI32.@)
1885 1886 1887 1888 1889 1890
 *
 * Signs data.
 *
 * PARAMS
 *  hHash        [I] Handle of the hash object to be signed.
 *  dwKeySpec    [I] Private key to use.
1891
 *  sDescription [I] Should be NULL.
1892 1893 1894 1895 1896 1897 1898
 *  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
1899 1900 1901 1902 1903
 *
 * NOTES
 *  Because of security flaws sDescription should not be used and should thus be
 *  NULL. It is supported only for compatibility with Microsoft's Cryptographic
 *  Providers.
1904
 */
1905
BOOL WINAPI CryptSignHashW (HCRYPTHASH hHash, DWORD dwKeySpec, LPCWSTR sDescription,
1906 1907
		DWORD dwFlags, BYTE *pbSignature, DWORD *pdwSigLen)
{
1908 1909
	PCRYPTHASH hash = (PCRYPTHASH)hHash;
	PCRYPTPROV prov;
1910

1911
	TRACE("(0x%lx, %d, %s, %08x, %p, %p)\n", 
1912
		hHash, dwKeySpec, debugstr_w(sDescription), dwFlags, pbSignature, pdwSigLen);
1913 1914

	if (!hash)
1915 1916 1917 1918
	{
		SetLastError(ERROR_INVALID_HANDLE);
		return FALSE;
	}
1919 1920
	if (!pdwSigLen || !hash->pProvider || hash->dwMagic != MAGIC_CRYPTHASH ||
		 hash->pProvider->dwMagic != MAGIC_CRYPTPROV)
1921 1922 1923 1924
	{
		SetLastError(ERROR_INVALID_PARAMETER);
		return FALSE;
	}
1925 1926

	prov = hash->pProvider;
1927
	return prov->pFuncs->pCPSignHash(prov->hPrivate, hash->hPrivate, dwKeySpec, sDescription,
1928
		dwFlags, pbSignature, pdwSigLen);
1929 1930
}

1931 1932 1933
/******************************************************************************
 * CryptSignHashA (ADVAPI32.@)
 *
1934
 * See CryptSignHashW.
1935 1936 1937 1938 1939 1940 1941
 */
BOOL WINAPI CryptSignHashA (HCRYPTHASH hHash, DWORD dwKeySpec, LPCSTR sDescription,
		DWORD dwFlags, BYTE *pbSignature, DWORD *pdwSigLen)
{
	LPWSTR wsDescription;
	BOOL result;

1942
	TRACE("(0x%lx, %d, %s, %08x, %p, %p)\n", 
1943 1944 1945 1946
		hHash, dwKeySpec, debugstr_a(sDescription), dwFlags, pbSignature, pdwSigLen);

	CRYPT_ANSIToUnicode(sDescription, &wsDescription, -1);
	result = CryptSignHashW(hHash, dwKeySpec, wsDescription, dwFlags, pbSignature, pdwSigLen);
1947
	CRYPT_Free(wsDescription);
1948 1949 1950 1951

	return result;
}

1952 1953
/******************************************************************************
 * CryptSetHashParam (ADVAPI32.@)
1954 1955 1956 1957 1958 1959 1960 1961 1962 1963 1964 1965
 *
 * 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
1966
 */
1967
BOOL WINAPI CryptSetHashParam (HCRYPTHASH hHash, DWORD dwParam, const BYTE *pbData, DWORD dwFlags)
1968
{
1969 1970 1971
	PCRYPTPROV prov;
	PCRYPTHASH hash = (PCRYPTHASH)hHash;

1972
	TRACE("(0x%lx, %d, %p, %08x)\n", hHash, dwParam, pbData, dwFlags);
1973

1974 1975
	if (!hash || !pbData || !hash->pProvider ||
		hash->dwMagic != MAGIC_CRYPTHASH || hash->pProvider->dwMagic != MAGIC_CRYPTPROV)
1976 1977 1978 1979
	{
		SetLastError(ERROR_INVALID_PARAMETER);
		return FALSE;
	}
1980 1981 1982 1983

	prov = hash->pProvider;
	return prov->pFuncs->pCPSetHashParam(prov->hPrivate, hash->hPrivate,
			dwParam, pbData, dwFlags);
1984 1985 1986
}

/******************************************************************************
1987
 * CryptSetKeyParam (ADVAPI32.@)
1988 1989 1990 1991 1992 1993 1994 1995 1996 1997 1998 1999
 *
 * 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
2000
 */
2001
BOOL WINAPI CryptSetKeyParam (HCRYPTKEY hKey, DWORD dwParam, const BYTE *pbData, DWORD dwFlags)
2002
{
2003 2004 2005
	PCRYPTPROV prov;
	PCRYPTKEY key = (PCRYPTKEY)hKey;

2006
	TRACE("(0x%lx, %d, %p, %08x)\n", hKey, dwParam, pbData, dwFlags);
2007

2008 2009
	if (!key || !pbData || !key->pProvider ||
		key->dwMagic != MAGIC_CRYPTKEY || key->pProvider->dwMagic != MAGIC_CRYPTPROV)
2010 2011 2012 2013
	{
		SetLastError(ERROR_INVALID_PARAMETER);
		return FALSE;
	}
2014 2015 2016 2017

	prov = key->pProvider;
	return prov->pFuncs->pCPSetKeyParam(prov->hPrivate, key->hPrivate,
			dwParam, pbData, dwFlags);
2018 2019 2020 2021
}

/******************************************************************************
 * CryptSetProviderA (ADVAPI32.@)
2022 2023 2024 2025 2026 2027 2028 2029 2030 2031
 *
 * 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
2032 2033 2034
 */
BOOL WINAPI CryptSetProviderA (LPCSTR pszProvName, DWORD dwProvType)
{
2035
	TRACE("(%s, %d)\n", pszProvName, dwProvType);
2036
	return CryptSetProviderExA(pszProvName, dwProvType, NULL, CRYPT_USER_DEFAULT);
2037 2038 2039 2040
}

/******************************************************************************
 * CryptSetProviderW (ADVAPI32.@)
2041
 *
2042
 * See CryptSetProviderA.
2043 2044 2045
 */
BOOL WINAPI CryptSetProviderW (LPCWSTR pszProvName, DWORD dwProvType)
{
2046
	TRACE("(%s, %d)\n", debugstr_w(pszProvName), dwProvType);
2047
	return CryptSetProviderExW(pszProvName, dwProvType, NULL, CRYPT_USER_DEFAULT);
2048 2049 2050
}

/******************************************************************************
2051
 * CryptSetProviderExW (ADVAPI32.@)
2052 2053 2054 2055 2056 2057 2058 2059 2060 2061 2062 2063
 *
 * 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
2064
 */
2065
BOOL WINAPI CryptSetProviderExW (LPCWSTR pszProvName, DWORD dwProvType, DWORD *pdwReserved, DWORD dwFlags)
2066
{
2067
	HKEY hProvKey, hTypeKey;
2068 2069
	PWSTR keyname;
	static const WCHAR nameW[] = {'N','a','m','e',0};
2070

2071
	TRACE("(%s, %d, %p, %08x)\n", debugstr_w(pszProvName), dwProvType, pdwReserved, dwFlags);
2072 2073

	if (!pszProvName || pdwReserved)
2074 2075 2076 2077
	{
		SetLastError(ERROR_INVALID_PARAMETER);
		return FALSE;
	}
2078
	if (dwProvType > MAXPROVTYPES)
2079 2080 2081 2082
	{
		SetLastError(NTE_BAD_PROV_TYPE);
		return FALSE;
	}
2083 2084
	if (dwFlags & ~(CRYPT_MACHINE_DEFAULT | CRYPT_USER_DEFAULT | CRYPT_DELETE_DEFAULT)
			|| dwFlags == CRYPT_DELETE_DEFAULT)
2085 2086 2087 2088 2089
	{
		SetLastError(NTE_BAD_FLAGS);
		return FALSE;
	}

2090
	if (!(keyname = CRYPT_GetTypeKeyName(dwProvType, dwFlags & CRYPT_USER_DEFAULT)))
2091 2092 2093 2094
	{
		SetLastError(ERROR_NOT_ENOUGH_MEMORY);
		return FALSE;
	}
2095
	if (RegOpenKeyW((dwFlags & CRYPT_USER_DEFAULT) ? HKEY_CURRENT_USER : HKEY_LOCAL_MACHINE,
2096
		keyname, &hTypeKey))
2097 2098
	{
		CRYPT_Free(keyname);
2099 2100
		SetLastError(NTE_BAD_PROVIDER);
		return FALSE;
2101 2102
	}
	CRYPT_Free(keyname);
2103 2104 2105
	
	if (dwFlags & CRYPT_DELETE_DEFAULT)
	{
2106
		RegDeleteValueW(hTypeKey, nameW);
2107 2108 2109 2110 2111 2112
	}
	else
	{
		if (!(keyname = CRYPT_GetProvKeyName(pszProvName)))
		{
			RegCloseKey(hTypeKey);
2113 2114
			SetLastError(ERROR_NOT_ENOUGH_MEMORY);
			return FALSE;
2115
		}
2116
		if (RegOpenKeyW((dwFlags & CRYPT_USER_DEFAULT) ? HKEY_CURRENT_USER : HKEY_LOCAL_MACHINE,
2117 2118 2119 2120
			keyname, &hProvKey))
		{
			CRYPT_Free(keyname);
			RegCloseKey(hTypeKey);
2121 2122
			SetLastError(NTE_BAD_PROVIDER);
			return FALSE;
2123 2124 2125
		}
		CRYPT_Free(keyname);
		
2126 2127
		if (RegSetValueExW(hTypeKey, nameW, 0, REG_SZ, (const BYTE *)pszProvName,
			(strlenW(pszProvName) + 1)*sizeof(WCHAR)))
2128 2129 2130 2131 2132 2133 2134 2135 2136 2137
		{
			RegCloseKey(hTypeKey);
			RegCloseKey(hProvKey);
			return FALSE;
		}
		
		RegCloseKey(hProvKey);
	}
	RegCloseKey(hTypeKey);

2138
	return TRUE;
2139 2140 2141
}

/******************************************************************************
2142
 * CryptSetProviderExA (ADVAPI32.@)
2143
 *
2144
 * See CryptSetProviderExW.
2145
 */
2146
BOOL WINAPI CryptSetProviderExA (LPCSTR pszProvName, DWORD dwProvType, DWORD *pdwReserved, DWORD dwFlags)
2147
{
2148
	BOOL ret = FALSE;
2149
	PWSTR str = NULL;
2150

2151
	TRACE("(%s, %d, %p, %08x)\n", pszProvName, dwProvType, pdwReserved, dwFlags);
2152

2153
	if (CRYPT_ANSIToUnicode(pszProvName, &str, -1))
2154
	{
2155
		ret = CryptSetProviderExW(str, dwProvType, pdwReserved, dwFlags);
2156 2157 2158
		CRYPT_Free(str);
	}
	return ret;
2159 2160 2161 2162
}

/******************************************************************************
 * CryptSetProvParam (ADVAPI32.@)
2163 2164 2165 2166 2167 2168 2169 2170 2171 2172 2173 2174
 *
 * 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
2175
 */
2176
BOOL WINAPI CryptSetProvParam (HCRYPTPROV hProv, DWORD dwParam, const BYTE *pbData, DWORD dwFlags)
2177
{
2178 2179
	PCRYPTPROV prov = (PCRYPTPROV)hProv;

2180
	TRACE("(0x%lx, %d, %p, %08x)\n", hProv, dwParam, pbData, dwFlags);
2181 2182

	if (!prov)
2183 2184 2185 2186
	{
		SetLastError(ERROR_INVALID_HANDLE);
		return FALSE;
	}
2187
	if (prov->dwMagic != MAGIC_CRYPTPROV)
2188 2189 2190 2191
	{
		SetLastError(ERROR_INVALID_PARAMETER);
		return FALSE;
	}
2192
	if (dwParam == PP_USE_HARDWARE_RNG)
2193 2194 2195 2196 2197 2198
	{
		FIXME("PP_USE_HARDWARE_RNG: What do I do with this?\n");
		FIXME("\tLetting the CSP decide.\n");
	}
	if (dwFlags & PP_CLIENT_HWND)
	{
2199 2200
		/* FIXME: Should verify the parameter */
		if (pbData /* && IsWindow((HWND)pbData) */)
2201 2202 2203 2204 2205 2206 2207 2208
		{
			crypt_hWindow = (HWND)(pbData);
			return TRUE;
		} else {
			SetLastError(ERROR_INVALID_PARAMETER);
			return FALSE;
		}
	}
2209
	/* All other flags go to the CSP */
2210
	return prov->pFuncs->pCPSetProvParam(prov->hPrivate, dwParam, pbData, dwFlags);
2211 2212 2213
}

/******************************************************************************
2214
 * CryptVerifySignatureW (ADVAPI32.@)
2215 2216 2217 2218 2219 2220 2221 2222
 *
 * 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.
2223
 *  sDescription [I] Should be NULL.
2224 2225 2226 2227 2228
 *  dwFlags      [I] See MSDN doc.
 *
 * RETURNS
 *  Success: TRUE
 *  Failure: FALSE
2229 2230 2231 2232 2233
 * 
 * NOTES
 *  Because of security flaws sDescription should not be used and should thus be
 *  NULL. It is supported only for compatibility with Microsoft's Cryptographic
 *  Providers.
2234
 */
2235
BOOL WINAPI CryptVerifySignatureW (HCRYPTHASH hHash, const BYTE *pbSignature, DWORD dwSigLen,
2236
		HCRYPTKEY hPubKey, LPCWSTR sDescription, DWORD dwFlags)
2237
{
2238 2239 2240
	PCRYPTHASH hash = (PCRYPTHASH)hHash;
	PCRYPTKEY key = (PCRYPTKEY)hPubKey;
	PCRYPTPROV prov;
2241

2242
	TRACE("(0x%lx, %p, %d, 0x%lx, %s, %08x)\n", hHash, pbSignature,
2243
			dwSigLen, hPubKey, debugstr_w(sDescription), dwFlags);
2244

2245
	if (!hash || !key || key->dwMagic != MAGIC_CRYPTKEY || hash->dwMagic != MAGIC_CRYPTHASH ||
2246 2247 2248
	    !hash->pProvider || hash->pProvider->dwMagic != MAGIC_CRYPTPROV ||
	    !key->pProvider || key->pProvider->dwMagic != MAGIC_CRYPTPROV)
	{
2249 2250
		SetLastError(ERROR_INVALID_PARAMETER);
		return FALSE;
2251 2252
	}
		
2253 2254
	prov = hash->pProvider;
	return prov->pFuncs->pCPVerifySignature(prov->hPrivate, hash->hPrivate, pbSignature, dwSigLen,
2255
		key->hPrivate, sDescription, dwFlags);
2256
}
2257

2258 2259 2260
/******************************************************************************
 * CryptVerifySignatureA (ADVAPI32.@)
 *
2261
 * See CryptVerifySignatureW.
2262
 */
2263
BOOL WINAPI CryptVerifySignatureA (HCRYPTHASH hHash, const BYTE *pbSignature, DWORD dwSigLen,
2264 2265 2266 2267 2268
		HCRYPTKEY hPubKey, LPCSTR sDescription, DWORD dwFlags)
{
	LPWSTR wsDescription;
	BOOL result;

2269
	TRACE("(0x%lx, %p, %d, 0x%lx, %s, %08x)\n", hHash, pbSignature,
2270 2271 2272 2273
			dwSigLen, hPubKey, debugstr_a(sDescription), dwFlags);

	CRYPT_ANSIToUnicode(sDescription, &wsDescription, -1);
	result = CryptVerifySignatureW(hHash, pbSignature, dwSigLen, hPubKey, wsDescription, dwFlags);
2274
	CRYPT_Free(wsDescription);
2275 2276 2277

	return result;
}
2278

2279 2280 2281 2282 2283 2284 2285 2286 2287 2288 2289 2290 2291 2292 2293 2294 2295 2296 2297 2298 2299 2300 2301 2302 2303 2304 2305 2306 2307 2308
/******************************************************************************
 * OpenEncryptedFileRawA   (ADVAPI32.@)
 *
 * See OpenEncryptedFileRawW
 */
DWORD WINAPI OpenEncryptedFileRawA(LPCSTR filename, ULONG flags, PVOID *context)
{
    FIXME("(%s, %x, %p): stub\n", debugstr_a(filename), flags, context);
    return ERROR_CALL_NOT_IMPLEMENTED;
}

/******************************************************************************
 * OpenEncryptedFileRawW   (ADVAPI32.@)
 *
 * Opens an EFS encrypted file for backup/restore
 *
 * PARAMS
 *  filename   [I] Filename to operate on
 *  flags     [I] Operation to perform
 *  context    [I] Handle to the context (out)
 * RETURNS
 *  Success: ERROR_SUCCESS
 *  Failure: NTSTATUS error code
 */
DWORD WINAPI OpenEncryptedFileRawW(LPCWSTR filename, ULONG flags, PVOID *context)
{
    FIXME("(%s, %x, %p): stub\n", debugstr_w(filename), flags, context);
    return ERROR_CALL_NOT_IMPLEMENTED;
}

2309 2310 2311 2312 2313 2314 2315 2316 2317 2318 2319 2320 2321 2322 2323 2324 2325 2326 2327
/******************************************************************************
 * ReadEncryptedFileRaw   (ADVAPI32.@)
 *
 * Export encrypted files
 *
 * PARAMS
 *  export   [I] pointer to the export callback function
 *  callback     [I] pointer to the application defined context
 *  context    [I] pointer to the system context
 * RETURNS
 *  Success: ERROR_SUCCESS
 *  Failure: NTSTATUS error code
 */
DWORD WINAPI ReadEncryptedFileRaw(PFE_EXPORT_FUNC export, PVOID callback, PVOID context)
{
    FIXME("(%p, %p, %p): stub\n", export, callback, context);
    return ERROR_CALL_NOT_IMPLEMENTED;
}

2328
/******************************************************************************
2329
 * SystemFunction030   (ADVAPI32.@)
2330 2331 2332 2333 2334 2335 2336 2337 2338 2339
 *
 * Tests if two blocks of 16 bytes are equal
 *
 * PARAMS
 *  b1,b2   [I] block of 16 bytes
 *
 * RETURNS
 *  TRUE  if blocks are the same
 *  FALSE if blocks are different
 */
2340
BOOL WINAPI SystemFunction030(LPCVOID b1, LPCVOID b2)
2341 2342 2343 2344
{
    return !memcmp(b1, b2, 0x10);
}

2345 2346 2347 2348 2349 2350 2351 2352 2353 2354 2355 2356 2357 2358 2359
/******************************************************************************
 * SystemFunction035   (ADVAPI32.@)
 *
 * Described here:
http://disc.server.com/discussion.cgi?disc=148775;article=942;title=Coding%2FASM%2FSystem
 *
 * NOTES
 *  Stub, always return TRUE.
 */
BOOL WINAPI SystemFunction035(LPCSTR lpszDllFilePath)
{
    FIXME("%s: stub\n", debugstr_a(lpszDllFilePath));
    return TRUE;
}

2360 2361 2362 2363 2364 2365
/******************************************************************************
 * SystemFunction036   (ADVAPI32.@)
 *
 * MSDN documents this function as RtlGenRandom and declares it in ntsecapi.h
 *
 * PARAMS
2366
 *  pbBuffer [O] Pointer to memory to receive random bytes.
2367
 *  dwLen   [I] Number of random bytes to fetch.
2368 2369 2370 2371
 *
 * RETURNS
 *  Success: TRUE
 *  Failure: FALSE
2372 2373
 */

2374
BOOLEAN WINAPI SystemFunction036(PVOID pbBuffer, ULONG dwLen)
2375 2376 2377 2378 2379 2380 2381 2382 2383 2384 2385 2386 2387
{
    int dev_random;

    dev_random = open("/dev/urandom", O_RDONLY);
    if (dev_random != -1)
    {
        if (read(dev_random, pbBuffer, dwLen) == (ssize_t)dwLen)
        {
            close(dev_random);
            return TRUE;
        }
        close(dev_random);
    }
2388 2389
    else
        FIXME("couldn't open /dev/urandom\n");
2390 2391 2392 2393
    SetLastError(NTE_FAIL);
    return FALSE;
}    
    
2394 2395 2396 2397 2398 2399 2400 2401
/*
   These functions have nearly identical prototypes to CryptProtectMemory and CryptUnprotectMemory,
   in crypt32.dll.
 */

/******************************************************************************
 * SystemFunction040   (ADVAPI32.@)
 *
2402
 * MSDN documents this function as RtlEncryptMemory and declares it in ntsecapi.h.
2403
 *
2404 2405 2406 2407 2408 2409 2410 2411
 * PARAMS
 *  memory [I/O] Pointer to memory to encrypt.
 *  length [I] Length of region to encrypt in bytes.
 *  flags  [I] Control whether other processes are able to decrypt the memory.
 *    RTL_ENCRYPT_OPTION_SAME_PROCESS 
 *    RTL_ENCRYPT_OPTION_CROSS_PROCESS 
 *    RTL_ENCRYPT_OPTION_SAME_LOGON
 *    
2412 2413 2414 2415
 * RETURNS
 *  Success: STATUS_SUCCESS
 *  Failure: NTSTATUS error code
 *
2416 2417 2418 2419
 * NOTES
 *  length must be a multiple of RTL_ENCRYPT_MEMORY_SIZE.
 *  If flags are specified when encrypting, the same flag value must be given
 *  when decrypting the memory.
2420
 */
2421
NTSTATUS WINAPI SystemFunction040(PVOID memory, ULONG length, ULONG flags)
2422
{
2423
	FIXME("(%p, %x, %x): stub [RtlEncryptMemory]\n", memory, length, flags);
2424 2425 2426 2427 2428 2429
	return STATUS_SUCCESS;
}

/******************************************************************************
 * SystemFunction041  (ADVAPI32.@)
 *
2430
 * MSDN documents this function as RtlDecryptMemory and declares it in ntsecapi.h.
2431
 *
2432 2433 2434 2435 2436 2437 2438 2439
 * PARAMS
 *  memory [I/O] Pointer to memory to decrypt.
 *  length [I] Length of region to decrypt in bytes.
 *  flags  [I] Control whether other processes are able to decrypt the memory.
 *    RTL_ENCRYPT_OPTION_SAME_PROCESS
 *    RTL_ENCRYPT_OPTION_CROSS_PROCESS
 *    RTL_ENCRYPT_OPTION_SAME_LOGON
 *
2440 2441 2442 2443
 * RETURNS
 *  Success: STATUS_SUCCESS
 *  Failure: NTSTATUS error code
 *
2444 2445 2446 2447
 * NOTES
 *  length must be a multiple of RTL_ENCRYPT_MEMORY_SIZE.
 *  If flags are specified when encrypting, the same flag value must be given
 *  when decrypting the memory.
2448
 */
2449
NTSTATUS WINAPI SystemFunction041(PVOID memory, ULONG length, ULONG flags)
2450
{
2451
	FIXME("(%p, %x, %x): stub [RtlDecryptMemory]\n", memory, length, flags);
2452 2453
	return STATUS_SUCCESS;
}
2454 2455 2456 2457 2458 2459 2460 2461 2462 2463 2464 2465 2466 2467 2468 2469 2470 2471 2472

/******************************************************************************
 * WriteEncryptedFileRaw   (ADVAPI32.@)
 *
 * Import encrypted files
 *
 * PARAMS
 *  import   [I] pointer to the import callback function
 *  callback     [I] pointer to the application defined context
 *  context    [I] pointer to the system context
 * RETURNS
 *  Success: ERROR_SUCCESS
 *  Failure: NTSTATUS error code
 */
DWORD WINAPI WriteEncryptedFileRaw(PFE_IMPORT_FUNC import, PVOID callback, PVOID context)
{
    FIXME("(%p, %p, %p): stub\n", import, callback, context);
    return ERROR_CALL_NOT_IMPLEMENTED;
}