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