[CRYPT32]
[reactos.git] / reactos / dll / win32 / crypt32 / sip.c
1 /*
2 * Copyright 2002 Mike McCormack for CodeWeavers
3 * Copyright 2005-2008 Juan Lang
4 * Copyright 2006 Paul Vriens
5 *
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
10 *
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
15 *
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
19 */
20
21 #include "crypt32_private.h"
22
23 WINE_DEFAULT_DEBUG_CHANNEL(crypt);
24
25 static const WCHAR szOID[] = {
26 'S','o','f','t','w','a','r','e','\\',
27 'M','i','c','r','o','s','o','f','t','\\',
28 'C','r','y','p','t','o','g','r','a','p','h','y','\\',
29 'O','I','D','\\',
30 'E','n','c','o','d','i','n','g','T','y','p','e',' ','0','\\',
31 'C','r','y','p','t','S','I','P','D','l','l', 0 };
32
33 static const WCHAR szPutSigned[] = {
34 'P','u','t','S','i','g','n','e','d','D','a','t','a','M','s','g','\\',0};
35 static const WCHAR szGetSigned[] = {
36 'G','e','t','S','i','g','n','e','d','D','a','t','a','M','s','g','\\',0};
37 static const WCHAR szRemoveSigned[] = {
38 'R','e','m','o','v','e','S','i','g','n','e','d','D','a','t','a','M','s','g','\\',0};
39 static const WCHAR szCreate[] = {
40 'C','r','e','a','t','e','I','n','d','i','r','e','c','t','D','a','t','a','\\',0};
41 static const WCHAR szVerify[] = {
42 'V','e','r','i','f','y','I','n','d','i','r','e','c','t','D','a','t','a','\\',0};
43 static const WCHAR szIsMyFile[] = {
44 'I','s','M','y','F','i','l','e','T','y','p','e','\\',0};
45 static const WCHAR szIsMyFile2[] = {
46 'I','s','M','y','F','i','l','e','T','y','p','e','2','\\',0};
47
48 static const WCHAR szDllName[] = { 'D','l','l',0 };
49 static const WCHAR szFuncName[] = { 'F','u','n','c','N','a','m','e',0 };
50
51 /* convert a guid to a wide character string */
52 static void CRYPT_guid2wstr( const GUID *guid, LPWSTR wstr )
53 {
54 char str[40];
55
56 sprintf(str, "{%08X-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X}",
57 guid->Data1, guid->Data2, guid->Data3,
58 guid->Data4[0], guid->Data4[1], guid->Data4[2], guid->Data4[3],
59 guid->Data4[4], guid->Data4[5], guid->Data4[6], guid->Data4[7] );
60 MultiByteToWideChar( CP_ACP, 0, str, -1, wstr, 40 );
61 }
62
63 /***********************************************************************
64 * CRYPT_SIPDeleteFunction
65 *
66 * Helper function for CryptSIPRemoveProvider
67 */
68 static LONG CRYPT_SIPDeleteFunction( const GUID *guid, LPCWSTR szKey )
69 {
70 WCHAR szFullKey[ 0x100 ];
71 LONG r = ERROR_SUCCESS;
72
73 /* max length of szFullKey depends on our code only, so we won't overrun */
74 lstrcpyW( szFullKey, szOID );
75 lstrcatW( szFullKey, szKey );
76 CRYPT_guid2wstr( guid, &szFullKey[ lstrlenW( szFullKey ) ] );
77
78 r = RegDeleteKeyW(HKEY_LOCAL_MACHINE, szFullKey);
79
80 return r;
81 }
82
83 /***********************************************************************
84 * CryptSIPRemoveProvider (CRYPT32.@)
85 *
86 * Remove a SIP provider and its functions from the registry.
87 *
88 * PARAMS
89 * pgProv [I] Pointer to a GUID for this SIP provider
90 *
91 * RETURNS
92 * Success: TRUE.
93 * Failure: FALSE. (Look at GetLastError()).
94 *
95 * NOTES
96 * Registry errors are always reported via SetLastError(). Every registry
97 * deletion will be tried.
98 */
99 BOOL WINAPI CryptSIPRemoveProvider(GUID *pgProv)
100 {
101 LONG r = ERROR_SUCCESS;
102 LONG remove_error = ERROR_SUCCESS;
103
104 TRACE("%s\n", debugstr_guid(pgProv));
105
106 if (!pgProv)
107 {
108 SetLastError(ERROR_INVALID_PARAMETER);
109 return FALSE;
110 }
111
112
113 #define CRYPT_SIPREMOVEPROV( key ) \
114 r = CRYPT_SIPDeleteFunction( pgProv, key); \
115 if (r != ERROR_SUCCESS) remove_error = r
116
117 CRYPT_SIPREMOVEPROV( szPutSigned);
118 CRYPT_SIPREMOVEPROV( szGetSigned);
119 CRYPT_SIPREMOVEPROV( szRemoveSigned);
120 CRYPT_SIPREMOVEPROV( szCreate);
121 CRYPT_SIPREMOVEPROV( szVerify);
122 CRYPT_SIPREMOVEPROV( szIsMyFile);
123 CRYPT_SIPREMOVEPROV( szIsMyFile2);
124
125 #undef CRYPT_SIPREMOVEPROV
126
127 if (remove_error != ERROR_SUCCESS)
128 {
129 SetLastError(remove_error);
130 return FALSE;
131 }
132
133 return TRUE;
134 }
135
136 /*
137 * Helper for CryptSIPAddProvider
138 *
139 * Add a registry key containing a dll name and function under
140 * "Software\\Microsoft\\Cryptography\\OID\\EncodingType 0\\<func>\\<guid>"
141 */
142 static LONG CRYPT_SIPWriteFunction( const GUID *guid, LPCWSTR szKey,
143 LPCWSTR szDll, LPCWSTR szFunction )
144 {
145 WCHAR szFullKey[ 0x100 ];
146 LONG r = ERROR_SUCCESS;
147 HKEY hKey;
148
149 if( !szFunction )
150 return ERROR_SUCCESS;
151
152 /* max length of szFullKey depends on our code only, so we won't overrun */
153 lstrcpyW( szFullKey, szOID );
154 lstrcatW( szFullKey, szKey );
155 CRYPT_guid2wstr( guid, &szFullKey[ lstrlenW( szFullKey ) ] );
156
157 TRACE("key is %s\n", debugstr_w( szFullKey ) );
158
159 r = RegCreateKeyW( HKEY_LOCAL_MACHINE, szFullKey, &hKey );
160 if( r != ERROR_SUCCESS ) goto error_close_key;
161
162 /* write the values */
163 r = RegSetValueExW( hKey, szFuncName, 0, REG_SZ, (const BYTE*) szFunction,
164 ( lstrlenW( szFunction ) + 1 ) * sizeof (WCHAR) );
165 if( r != ERROR_SUCCESS ) goto error_close_key;
166 r = RegSetValueExW( hKey, szDllName, 0, REG_SZ, (const BYTE*) szDll,
167 ( lstrlenW( szDll ) + 1) * sizeof (WCHAR) );
168
169 error_close_key:
170
171 RegCloseKey( hKey );
172
173 return r;
174 }
175
176 /***********************************************************************
177 * CryptSIPAddProvider (CRYPT32.@)
178 *
179 * Add a SIP provider and its functions to the registry.
180 *
181 * PARAMS
182 * psNewProv [I] Pointer to a structure with information about
183 * the functions this SIP provider can perform.
184 *
185 * RETURNS
186 * Success: TRUE.
187 * Failure: FALSE. (Look at GetLastError()).
188 *
189 * NOTES
190 * Registry errors are always reported via SetLastError(). If a
191 * registry error occurs the rest of the registry write operations
192 * will be skipped.
193 */
194 BOOL WINAPI CryptSIPAddProvider(SIP_ADD_NEWPROVIDER *psNewProv)
195 {
196 LONG r = ERROR_SUCCESS;
197
198 TRACE("%p\n", psNewProv);
199
200 if (!psNewProv ||
201 psNewProv->cbStruct < FIELD_OFFSET(SIP_ADD_NEWPROVIDER, pwszGetCapFuncName) ||
202 !psNewProv->pwszGetFuncName ||
203 !psNewProv->pwszPutFuncName ||
204 !psNewProv->pwszCreateFuncName ||
205 !psNewProv->pwszVerifyFuncName ||
206 !psNewProv->pwszRemoveFuncName)
207 {
208 SetLastError(ERROR_INVALID_PARAMETER);
209 return FALSE;
210 }
211
212 TRACE("%s %s %s %s %s\n",
213 debugstr_guid( psNewProv->pgSubject ),
214 debugstr_w( psNewProv->pwszDLLFileName ),
215 debugstr_w( psNewProv->pwszMagicNumber ),
216 debugstr_w( psNewProv->pwszIsFunctionName ),
217 debugstr_w( psNewProv->pwszIsFunctionNameFmt2 ) );
218
219 #define CRYPT_SIPADDPROV( key, field ) \
220 r = CRYPT_SIPWriteFunction( psNewProv->pgSubject, key, \
221 psNewProv->pwszDLLFileName, psNewProv->field); \
222 if (r != ERROR_SUCCESS) goto end_function
223
224 CRYPT_SIPADDPROV( szPutSigned, pwszPutFuncName );
225 CRYPT_SIPADDPROV( szGetSigned, pwszGetFuncName );
226 CRYPT_SIPADDPROV( szRemoveSigned, pwszRemoveFuncName );
227 CRYPT_SIPADDPROV( szCreate, pwszCreateFuncName );
228 CRYPT_SIPADDPROV( szVerify, pwszVerifyFuncName );
229 CRYPT_SIPADDPROV( szIsMyFile, pwszIsFunctionName );
230 CRYPT_SIPADDPROV( szIsMyFile2, pwszIsFunctionNameFmt2 );
231
232 #undef CRYPT_SIPADDPROV
233
234 end_function:
235
236 if (r != ERROR_SUCCESS)
237 {
238 SetLastError(r);
239 return FALSE;
240 }
241
242 return TRUE;
243 }
244
245 static void *CRYPT_LoadSIPFuncFromKey(HKEY key, HMODULE *pLib)
246 {
247 LONG r;
248 DWORD size;
249 WCHAR dllName[MAX_PATH];
250 char functionName[MAX_PATH];
251 HMODULE lib;
252 void *func = NULL;
253
254 /* Read the DLL entry */
255 size = sizeof(dllName);
256 r = RegQueryValueExW(key, szDllName, NULL, NULL, (LPBYTE)dllName, &size);
257 if (r) goto end;
258
259 /* Read the Function entry */
260 size = sizeof(functionName);
261 r = RegQueryValueExA(key, "FuncName", NULL, NULL, (LPBYTE)functionName,
262 &size);
263 if (r) goto end;
264
265 lib = LoadLibraryW(dllName);
266 if (!lib)
267 goto end;
268 func = GetProcAddress(lib, functionName);
269 if (func)
270 *pLib = lib;
271 else
272 FreeLibrary(lib);
273
274 end:
275 return func;
276 }
277
278 /***********************************************************************
279 * CryptSIPRetrieveSubjectGuid (CRYPT32.@)
280 *
281 * Determine the right SIP GUID for the given file.
282 *
283 * PARAMS
284 * FileName [I] Filename.
285 * hFileIn [I] Optional handle to the file.
286 * pgSubject [O] The SIP's GUID.
287 *
288 * RETURNS
289 * Success: TRUE. pgSubject contains the SIP GUID.
290 * Failure: FALSE. (Look at GetLastError()).
291 *
292 * NOTES
293 * On failure pgSubject will contain a NULL GUID.
294 * The handle is always preferred above the filename.
295 */
296 BOOL WINAPI CryptSIPRetrieveSubjectGuid
297 (LPCWSTR FileName, HANDLE hFileIn, GUID *pgSubject)
298 {
299 HANDLE hFile;
300 BOOL bRet = FALSE;
301 DWORD count;
302 LARGE_INTEGER zero, oldPos;
303 /* FIXME, find out if there is a name for this GUID */
304 static const GUID unknown = { 0xC689AAB8, 0x8E78, 0x11D0, { 0x8C,0x47,0x00,0xC0,0x4F,0xC2,0x95,0xEE }};
305 static const GUID cabGUID = { 0xc689aaba, 0x8e78, 0x11d0, {0x8c,0x47,0x00,0xc0,0x4f,0xc2,0x95,0xee }};
306 static const GUID catGUID = { 0xDE351A43, 0x8E59, 0x11D0, { 0x8C,0x47,0x00,0xC0,0x4F,0xC2,0x95,0xEE }};
307 static const WORD dosHdr = IMAGE_DOS_SIGNATURE;
308 static const BYTE cabHdr[] = { 'M','S','C','F' };
309 BYTE hdr[SIP_MAX_MAGIC_NUMBER];
310 WCHAR szFullKey[ 0x100 ];
311 LONG r = ERROR_SUCCESS;
312 HKEY key;
313
314 TRACE("(%s %p %p)\n", wine_dbgstr_w(FileName), hFileIn, pgSubject);
315
316 if (!pgSubject || (!FileName && !hFileIn))
317 {
318 SetLastError(ERROR_INVALID_PARAMETER);
319 return FALSE;
320 }
321
322 /* Set pgSubject to zero's */
323 memset(pgSubject, 0 , sizeof(GUID));
324
325 if (hFileIn)
326 /* Use the given handle, make sure not to close this one ourselves */
327 hFile = hFileIn;
328 else
329 {
330 hFile = CreateFileW(FileName, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
331 /* Last error is set by CreateFile */
332 if (hFile == INVALID_HANDLE_VALUE) return FALSE;
333 }
334
335 zero.QuadPart = 0;
336 SetFilePointerEx(hFile, zero, &oldPos, FILE_CURRENT);
337 SetFilePointer(hFile, 0, NULL, FILE_BEGIN);
338 if (!ReadFile(hFile, hdr, sizeof(hdr), &count, NULL))
339 goto cleanup;
340
341 if (count < SIP_MAX_MAGIC_NUMBER)
342 {
343 SetLastError(ERROR_INVALID_PARAMETER);
344 goto cleanup;
345 }
346
347 TRACE("file magic = 0x%02x%02x%02x%02x\n", hdr[0], hdr[1], hdr[2], hdr[3]);
348 /* As everything is in place now we start looking at the file header */
349 if (!memcmp(hdr, &dosHdr, sizeof(dosHdr)))
350 {
351 *pgSubject = unknown;
352 SetLastError(S_OK);
353 bRet = TRUE;
354 goto cleanup;
355 }
356 /* Quick-n-dirty check for a cab file. */
357 if (!memcmp(hdr, cabHdr, sizeof(cabHdr)))
358 {
359 *pgSubject = cabGUID;
360 SetLastError(S_OK);
361 bRet = TRUE;
362 goto cleanup;
363 }
364 /* If it's asn.1-encoded, it's probably a .cat file. */
365 if (hdr[0] == 0x30)
366 {
367 DWORD fileLen = GetFileSize(hFile, NULL);
368
369 TRACE("fileLen = %d\n", fileLen);
370 /* Sanity-check length */
371 if (hdr[1] < 0x80 && fileLen == 2 + hdr[1])
372 {
373 *pgSubject = catGUID;
374 SetLastError(S_OK);
375 bRet = TRUE;
376 goto cleanup;
377 }
378 else if (hdr[1] == 0x80)
379 {
380 /* Indefinite length, can't verify with just the header, assume it
381 * is.
382 */
383 *pgSubject = catGUID;
384 SetLastError(S_OK);
385 bRet = TRUE;
386 goto cleanup;
387 }
388 else
389 {
390 BYTE lenBytes = hdr[1] & 0x7f;
391
392 if (lenBytes == 1 && fileLen == 2 + lenBytes + hdr[2])
393 {
394 *pgSubject = catGUID;
395 SetLastError(S_OK);
396 bRet = TRUE;
397 goto cleanup;
398 }
399 else if (lenBytes == 2 && fileLen == 2 + lenBytes +
400 (hdr[2] << 8 | hdr[3]))
401 {
402 *pgSubject = catGUID;
403 SetLastError(S_OK);
404 bRet = TRUE;
405 goto cleanup;
406 }
407 else if (fileLen > 0xffff)
408 {
409 /* The file size must be greater than 2 bytes in length, so
410 * assume it is a .cat file
411 */
412 *pgSubject = catGUID;
413 SetLastError(S_OK);
414 bRet = TRUE;
415 goto cleanup;
416 }
417 }
418 }
419
420 /* Check for supported functions using CryptSIPDllIsMyFileType */
421 /* max length of szFullKey depends on our code only, so we won't overrun */
422 lstrcpyW(szFullKey, szOID);
423 lstrcatW(szFullKey, szIsMyFile);
424 r = RegOpenKeyExW(HKEY_LOCAL_MACHINE, szFullKey, 0, KEY_READ, &key);
425 if (r == ERROR_SUCCESS)
426 {
427 DWORD index = 0, size;
428 WCHAR subKeyName[MAX_PATH];
429
430 do {
431 size = sizeof(subKeyName) / sizeof(subKeyName[0]);
432 r = RegEnumKeyExW(key, index++, subKeyName, &size, NULL, NULL,
433 NULL, NULL);
434 if (r == ERROR_SUCCESS)
435 {
436 HKEY subKey;
437
438 r = RegOpenKeyExW(key, subKeyName, 0, KEY_READ, &subKey);
439 if (r == ERROR_SUCCESS)
440 {
441 HMODULE lib;
442 pfnIsFileSupported isMy = CRYPT_LoadSIPFuncFromKey(subKey,
443 &lib);
444
445 if (isMy)
446 {
447 bRet = isMy(hFile, pgSubject);
448 FreeLibrary(lib);
449 }
450 RegCloseKey(subKey);
451 }
452 }
453 } while (!bRet && r == ERROR_SUCCESS);
454 RegCloseKey(key);
455 }
456
457 /* Check for supported functions using CryptSIPDllIsMyFileType2 */
458 if (!bRet)
459 {
460 lstrcpyW(szFullKey, szOID);
461 lstrcatW(szFullKey, szIsMyFile2);
462 r = RegOpenKeyExW(HKEY_LOCAL_MACHINE, szFullKey, 0, KEY_READ, &key);
463 if (r == ERROR_SUCCESS)
464 {
465 DWORD index = 0, size;
466 WCHAR subKeyName[MAX_PATH];
467
468 do {
469 size = sizeof(subKeyName) / sizeof(subKeyName[0]);
470 r = RegEnumKeyExW(key, index++, subKeyName, &size, NULL, NULL,
471 NULL, NULL);
472 if (r == ERROR_SUCCESS)
473 {
474 HKEY subKey;
475
476 r = RegOpenKeyExW(key, subKeyName, 0, KEY_READ, &subKey);
477 if (r == ERROR_SUCCESS)
478 {
479 HMODULE lib;
480 pfnIsFileSupportedName isMy2 =
481 CRYPT_LoadSIPFuncFromKey(subKey, &lib);
482
483 if (isMy2)
484 {
485 bRet = isMy2((LPWSTR)FileName, pgSubject);
486 FreeLibrary(lib);
487 }
488 RegCloseKey(subKey);
489 }
490 }
491 } while (!bRet && r == ERROR_SUCCESS);
492 RegCloseKey(key);
493 }
494 }
495
496 if (!bRet)
497 SetLastError(TRUST_E_SUBJECT_FORM_UNKNOWN);
498
499 cleanup:
500 /* If we didn't open this one we shouldn't close it (hFile is a copy),
501 * but we should reset the file pointer to its original position.
502 */
503 if (!hFileIn)
504 CloseHandle(hFile);
505 else
506 SetFilePointerEx(hFile, oldPos, NULL, FILE_BEGIN);
507
508 return bRet;
509 }
510
511 static LONG CRYPT_OpenSIPFunctionKey(const GUID *guid, LPCWSTR function,
512 HKEY *key)
513 {
514 WCHAR szFullKey[ 0x100 ];
515
516 lstrcpyW(szFullKey, szOID);
517 lstrcatW(szFullKey, function);
518 CRYPT_guid2wstr(guid, &szFullKey[lstrlenW(szFullKey)]);
519 return RegOpenKeyExW(HKEY_LOCAL_MACHINE, szFullKey, 0, KEY_READ, key);
520 }
521
522 /* Loads the function named function for the SIP specified by pgSubject, and
523 * returns it if found. Returns NULL on error. If the function is loaded,
524 * *pLib is set to the library in which it is found.
525 */
526 static void *CRYPT_LoadSIPFunc(const GUID *pgSubject, LPCWSTR function,
527 HMODULE *pLib)
528 {
529 LONG r;
530 HKEY key;
531 void *func = NULL;
532
533 TRACE("(%s, %s)\n", debugstr_guid(pgSubject), debugstr_w(function));
534
535 r = CRYPT_OpenSIPFunctionKey(pgSubject, function, &key);
536 if (!r)
537 {
538 func = CRYPT_LoadSIPFuncFromKey(key, pLib);
539 RegCloseKey(key);
540 }
541 TRACE("returning %p\n", func);
542 return func;
543 }
544
545 typedef struct _WINE_SIP_PROVIDER {
546 GUID subject;
547 SIP_DISPATCH_INFO info;
548 struct list entry;
549 } WINE_SIP_PROVIDER;
550
551 static struct list providers = { &providers, &providers };
552 static CRITICAL_SECTION providers_cs;
553 static CRITICAL_SECTION_DEBUG providers_cs_debug =
554 {
555 0, 0, &providers_cs,
556 { &providers_cs_debug.ProcessLocksList,
557 &providers_cs_debug.ProcessLocksList },
558 0, 0, { (DWORD_PTR)(__FILE__ ": providers_cs") }
559 };
560 static CRITICAL_SECTION providers_cs = { &providers_cs_debug, -1, 0, 0, 0, 0 };
561
562 static void CRYPT_CacheSIP(const GUID *pgSubject, SIP_DISPATCH_INFO *info)
563 {
564 WINE_SIP_PROVIDER *prov = CryptMemAlloc(sizeof(WINE_SIP_PROVIDER));
565
566 if (prov)
567 {
568 prov->subject = *pgSubject;
569 prov->info = *info;
570 EnterCriticalSection(&providers_cs);
571 list_add_tail(&providers, &prov->entry);
572 LeaveCriticalSection(&providers_cs);
573 }
574 }
575
576 static WINE_SIP_PROVIDER *CRYPT_GetCachedSIP(const GUID *pgSubject)
577 {
578 WINE_SIP_PROVIDER *provider = NULL, *ret = NULL;
579
580 EnterCriticalSection(&providers_cs);
581 LIST_FOR_EACH_ENTRY(provider, &providers, WINE_SIP_PROVIDER, entry)
582 {
583 if (IsEqualGUID(pgSubject, &provider->subject))
584 break;
585 }
586 if (provider && IsEqualGUID(pgSubject, &provider->subject))
587 ret = provider;
588 LeaveCriticalSection(&providers_cs);
589 return ret;
590 }
591
592 static inline BOOL CRYPT_IsSIPCached(const GUID *pgSubject)
593 {
594 return CRYPT_GetCachedSIP(pgSubject) != NULL;
595 }
596
597 void crypt_sip_free(void)
598 {
599 WINE_SIP_PROVIDER *prov, *next;
600
601 LIST_FOR_EACH_ENTRY_SAFE(prov, next, &providers, WINE_SIP_PROVIDER, entry)
602 {
603 list_remove(&prov->entry);
604 FreeLibrary(prov->info.hSIP);
605 CryptMemFree(prov);
606 }
607 DeleteCriticalSection(&providers_cs);
608 }
609
610 /* Loads the SIP for pgSubject into the global cache. Returns FALSE if the
611 * SIP isn't registered or is invalid.
612 */
613 static BOOL CRYPT_LoadSIP(const GUID *pgSubject)
614 {
615 SIP_DISPATCH_INFO sip = { 0 };
616 HMODULE lib = NULL, temp = NULL;
617
618 sip.pfGet = CRYPT_LoadSIPFunc(pgSubject, szGetSigned, &lib);
619 if (!sip.pfGet)
620 goto error;
621 sip.pfPut = CRYPT_LoadSIPFunc(pgSubject, szPutSigned, &temp);
622 if (!sip.pfPut || temp != lib)
623 goto error;
624 FreeLibrary(temp);
625 temp = NULL;
626 sip.pfCreate = CRYPT_LoadSIPFunc(pgSubject, szCreate, &temp);
627 if (!sip.pfCreate || temp != lib)
628 goto error;
629 FreeLibrary(temp);
630 temp = NULL;
631 sip.pfVerify = CRYPT_LoadSIPFunc(pgSubject, szVerify, &temp);
632 if (!sip.pfVerify || temp != lib)
633 goto error;
634 FreeLibrary(temp);
635 temp = NULL;
636 sip.pfRemove = CRYPT_LoadSIPFunc(pgSubject, szRemoveSigned, &temp);
637 if (!sip.pfRemove || temp != lib)
638 goto error;
639 FreeLibrary(temp);
640 sip.hSIP = lib;
641 CRYPT_CacheSIP(pgSubject, &sip);
642 return TRUE;
643
644 error:
645 FreeLibrary(lib);
646 FreeLibrary(temp);
647 SetLastError(TRUST_E_SUBJECT_FORM_UNKNOWN);
648 return FALSE;
649 }
650
651 /***********************************************************************
652 * CryptSIPLoad (CRYPT32.@)
653 *
654 * Load some internal crypt32 functions into a SIP_DISPATCH_INFO structure.
655 *
656 * PARAMS
657 * pgSubject [I] The GUID.
658 * dwFlags [I] Flags.
659 * pSipDispatch [I] The loaded functions.
660 *
661 * RETURNS
662 * Success: TRUE. pSipDispatch contains the functions.
663 * Failure: FALSE. (Look at GetLastError()).
664 *
665 * NOTES
666 * CryptSIPLoad uses caching for the list of GUIDs and whether a SIP is
667 * already loaded.
668 *
669 * An application calls CryptSipLoad which will return a structure with the
670 * function addresses of some internal crypt32 functions. The application will
671 * then call these functions which will be forwarded to the appropriate SIP.
672 *
673 * CryptSIPLoad will load the needed SIP but doesn't unload this dll. The unloading
674 * is done when crypt32 is unloaded.
675 */
676 BOOL WINAPI CryptSIPLoad
677 (const GUID *pgSubject, DWORD dwFlags, SIP_DISPATCH_INFO *pSipDispatch)
678 {
679 TRACE("(%s %d %p)\n", debugstr_guid(pgSubject), dwFlags, pSipDispatch);
680
681 if (!pgSubject || dwFlags != 0 || !pSipDispatch)
682 {
683 SetLastError(ERROR_INVALID_PARAMETER);
684 return FALSE;
685 }
686 if (!CRYPT_IsSIPCached(pgSubject) && !CRYPT_LoadSIP(pgSubject))
687 return FALSE;
688
689 pSipDispatch->hSIP = NULL;
690 pSipDispatch->pfGet = CryptSIPGetSignedDataMsg;
691 pSipDispatch->pfPut = CryptSIPPutSignedDataMsg;
692 pSipDispatch->pfCreate = CryptSIPCreateIndirectData;
693 pSipDispatch->pfVerify = CryptSIPVerifyIndirectData;
694 pSipDispatch->pfRemove = CryptSIPRemoveSignedDataMsg;
695
696 return TRUE;
697 }
698
699 /***********************************************************************
700 * CryptSIPCreateIndirectData (CRYPT32.@)
701 */
702 BOOL WINAPI CryptSIPCreateIndirectData(SIP_SUBJECTINFO* pSubjectInfo, DWORD* pcbIndirectData,
703 SIP_INDIRECT_DATA* pIndirectData)
704 {
705 WINE_SIP_PROVIDER *sip;
706 BOOL ret = FALSE;
707
708 TRACE("(%p %p %p)\n", pSubjectInfo, pcbIndirectData, pIndirectData);
709
710 if (!pSubjectInfo || !pSubjectInfo->pgSubjectType || !pcbIndirectData)
711 {
712 SetLastError(ERROR_INVALID_PARAMETER);
713 return FALSE;
714 }
715 if ((sip = CRYPT_GetCachedSIP(pSubjectInfo->pgSubjectType)))
716 ret = sip->info.pfCreate(pSubjectInfo, pcbIndirectData, pIndirectData);
717 TRACE("returning %d\n", ret);
718 return ret;
719 }
720
721 /***********************************************************************
722 * CryptSIPGetSignedDataMsg (CRYPT32.@)
723 */
724 BOOL WINAPI CryptSIPGetSignedDataMsg(SIP_SUBJECTINFO* pSubjectInfo, DWORD* pdwEncodingType,
725 DWORD dwIndex, DWORD* pcbSignedDataMsg, BYTE* pbSignedDataMsg)
726 {
727 WINE_SIP_PROVIDER *sip;
728 BOOL ret = FALSE;
729
730 TRACE("(%p %p %d %p %p)\n", pSubjectInfo, pdwEncodingType, dwIndex,
731 pcbSignedDataMsg, pbSignedDataMsg);
732
733 if ((sip = CRYPT_GetCachedSIP(pSubjectInfo->pgSubjectType)))
734 ret = sip->info.pfGet(pSubjectInfo, pdwEncodingType, dwIndex,
735 pcbSignedDataMsg, pbSignedDataMsg);
736 TRACE("returning %d\n", ret);
737 return ret;
738 }
739
740 /***********************************************************************
741 * CryptSIPPutSignedDataMsg (CRYPT32.@)
742 */
743 BOOL WINAPI CryptSIPPutSignedDataMsg(SIP_SUBJECTINFO* pSubjectInfo, DWORD pdwEncodingType,
744 DWORD* pdwIndex, DWORD cbSignedDataMsg, BYTE* pbSignedDataMsg)
745 {
746 WINE_SIP_PROVIDER *sip;
747 BOOL ret = FALSE;
748
749 TRACE("(%p %d %p %d %p)\n", pSubjectInfo, pdwEncodingType, pdwIndex,
750 cbSignedDataMsg, pbSignedDataMsg);
751
752 if ((sip = CRYPT_GetCachedSIP(pSubjectInfo->pgSubjectType)))
753 ret = sip->info.pfPut(pSubjectInfo, pdwEncodingType, pdwIndex,
754 cbSignedDataMsg, pbSignedDataMsg);
755 TRACE("returning %d\n", ret);
756 return ret;
757 }
758
759 /***********************************************************************
760 * CryptSIPRemoveSignedDataMsg (CRYPT32.@)
761 */
762 BOOL WINAPI CryptSIPRemoveSignedDataMsg(SIP_SUBJECTINFO* pSubjectInfo,
763 DWORD dwIndex)
764 {
765 WINE_SIP_PROVIDER *sip;
766 BOOL ret = FALSE;
767
768 TRACE("(%p %d)\n", pSubjectInfo, dwIndex);
769
770 if ((sip = CRYPT_GetCachedSIP(pSubjectInfo->pgSubjectType)))
771 ret = sip->info.pfRemove(pSubjectInfo, dwIndex);
772 TRACE("returning %d\n", ret);
773 return ret;
774 }
775
776 /***********************************************************************
777 * CryptSIPVerifyIndirectData (CRYPT32.@)
778 */
779 BOOL WINAPI CryptSIPVerifyIndirectData(SIP_SUBJECTINFO* pSubjectInfo,
780 SIP_INDIRECT_DATA* pIndirectData)
781 {
782 WINE_SIP_PROVIDER *sip;
783 BOOL ret = FALSE;
784
785 TRACE("(%p %p)\n", pSubjectInfo, pIndirectData);
786
787 if ((sip = CRYPT_GetCachedSIP(pSubjectInfo->pgSubjectType)))
788 ret = sip->info.pfVerify(pSubjectInfo, pIndirectData);
789 TRACE("returning %d\n", ret);
790 return ret;
791 }