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