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