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