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