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