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