1 /* 2 * WinTrust Cryptography functions 3 * 4 * Copyright 2006 James Hawkins 5 * Copyright 2000-2002 Stuart Caie 6 * Copyright 2002 Patrik Stridvall 7 * Copyright 2003 Greg Turner 8 * Copyright 2008 Juan Lang 9 * 10 * This library is free software; you can redistribute it and/or 11 * modify it under the terms of the GNU Lesser General Public 12 * License as published by the Free Software Foundation; either 13 * version 2.1 of the License, or (at your option) any later version. 14 * 15 * This library is distributed in the hope that it will be useful, 16 * but WITHOUT ANY WARRANTY; without even the implied warranty of 17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 18 * Lesser General Public License for more details. 19 * 20 * You should have received a copy of the GNU Lesser General Public 21 * License along with this library; if not, write to the Free Software 22 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA 23 */ 24 25 #include <stdarg.h> 26 #include <stdio.h> 27 #include "windef.h" 28 #include "winbase.h" 29 #include "wintrust.h" 30 #include "mscat.h" 31 #include "mssip.h" 32 #include "imagehlp.h" 33 #include "winternl.h" 34 35 #include "wine/debug.h" 36 37 WINE_DEFAULT_DEBUG_CHANNEL(wintrust); 38 39 #define CATADMIN_MAGIC 0x43415441 /* 'CATA' */ 40 #define CRYPTCAT_MAGIC 0x43415443 /* 'CATC' */ 41 #define CATINFO_MAGIC 0x43415449 /* 'CATI' */ 42 43 struct cryptcat 44 { 45 DWORD magic; 46 HCRYPTMSG msg; 47 DWORD encoding; 48 CTL_INFO *inner; 49 DWORD inner_len; 50 GUID subject; 51 DWORD attr_count; 52 CRYPTCATATTRIBUTE *attr; 53 }; 54 55 struct catadmin 56 { 57 DWORD magic; 58 WCHAR path[MAX_PATH]; 59 HANDLE find; 60 }; 61 62 struct catinfo 63 { 64 DWORD magic; 65 WCHAR file[MAX_PATH]; 66 }; 67 68 static HCATINFO create_catinfo(const WCHAR *filename) 69 { 70 struct catinfo *ci; 71 72 if (!(ci = HeapAlloc(GetProcessHeap(), 0, sizeof(*ci)))) 73 { 74 SetLastError(ERROR_OUTOFMEMORY); 75 return INVALID_HANDLE_VALUE; 76 } 77 lstrcpyW(ci->file, filename); 78 ci->magic = CATINFO_MAGIC; 79 return ci; 80 } 81 82 /*********************************************************************** 83 * CryptCATAdminAcquireContext (WINTRUST.@) 84 * 85 * Get a catalog administrator context handle. 86 * 87 * PARAMS 88 * catAdmin [O] Pointer to the context handle. 89 * sys [I] Pointer to a GUID for the needed subsystem. 90 * dwFlags [I] Reserved. 91 * 92 * RETURNS 93 * Success: TRUE. catAdmin contains the context handle. 94 * Failure: FALSE. 95 * 96 */ 97 BOOL WINAPI CryptCATAdminAcquireContext(HCATADMIN *catAdmin, 98 const GUID *sys, DWORD dwFlags) 99 { 100 static const WCHAR catroot[] = 101 {'\\','c','a','t','r','o','o','t',0}; 102 static const WCHAR fmt[] = 103 {'%','s','\\','{','%','0','8','x','-','%','0','4','x','-','%','0', 104 '4','x','-','%','0','2','x','%','0','2','x','-','%','0','2','x', 105 '%','0','2','x','%','0','2','x','%','0','2','x','%','0','2','x', 106 '%','0','2','x','}',0}; 107 static const GUID defsys = 108 {0x127d0a1d,0x4ef2,0x11d1,{0x86,0x08,0x00,0xc0,0x4f,0xc2,0x95,0xee}}; 109 110 WCHAR catroot_dir[MAX_PATH]; 111 struct catadmin *ca; 112 113 TRACE("%p %s %x\n", catAdmin, debugstr_guid(sys), dwFlags); 114 115 if (!catAdmin || dwFlags) 116 { 117 SetLastError(ERROR_INVALID_PARAMETER); 118 return FALSE; 119 } 120 if (!(ca = HeapAlloc(GetProcessHeap(), 0, sizeof(*ca)))) 121 { 122 SetLastError(ERROR_OUTOFMEMORY); 123 return FALSE; 124 } 125 126 GetSystemDirectoryW(catroot_dir, MAX_PATH); 127 lstrcatW(catroot_dir, catroot); 128 129 /* create the directory if it doesn't exist */ 130 CreateDirectoryW(catroot_dir, NULL); 131 132 if (!sys) sys = &defsys; 133 swprintf(ca->path, fmt, catroot_dir, sys->Data1, sys->Data2, 134 sys->Data3, sys->Data4[0], sys->Data4[1], sys->Data4[2], 135 sys->Data4[3], sys->Data4[4], sys->Data4[5], sys->Data4[6], 136 sys->Data4[7]); 137 138 /* create the directory if it doesn't exist */ 139 CreateDirectoryW(ca->path, NULL); 140 141 ca->magic = CATADMIN_MAGIC; 142 ca->find = INVALID_HANDLE_VALUE; 143 144 *catAdmin = ca; 145 return TRUE; 146 } 147 148 /*********************************************************************** 149 * CryptCATAdminAcquireContext2 (WINTRUST.@) 150 */ 151 BOOL WINAPI CryptCATAdminAcquireContext2(HCATADMIN *catAdmin, const GUID *sys, const WCHAR *algorithm, 152 const CERT_STRONG_SIGN_PARA *policy, DWORD flags) 153 { 154 FIXME("%p %s %s %p %x stub\n", catAdmin, debugstr_guid(sys), debugstr_w(algorithm), policy, flags); 155 SetLastError(ERROR_CALL_NOT_IMPLEMENTED); 156 return FALSE; 157 } 158 159 /*********************************************************************** 160 * CryptCATAdminAddCatalog (WINTRUST.@) 161 */ 162 HCATINFO WINAPI CryptCATAdminAddCatalog(HCATADMIN catAdmin, PWSTR catalogFile, 163 PWSTR selectBaseName, DWORD flags) 164 { 165 static const WCHAR slashW[] = {'\\',0}; 166 struct catadmin *ca = catAdmin; 167 struct catinfo *ci; 168 WCHAR *target; 169 DWORD len; 170 171 TRACE("%p %s %s %d\n", catAdmin, debugstr_w(catalogFile), 172 debugstr_w(selectBaseName), flags); 173 174 if (!selectBaseName) 175 { 176 FIXME("NULL basename not handled\n"); 177 SetLastError(ERROR_INVALID_PARAMETER); 178 return NULL; 179 } 180 if (!ca || ca->magic != CATADMIN_MAGIC || !catalogFile || flags) 181 { 182 SetLastError(ERROR_INVALID_PARAMETER); 183 return NULL; 184 } 185 186 len = lstrlenW(ca->path) + lstrlenW(selectBaseName) + 2; 187 if (!(target = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR)))) 188 { 189 SetLastError(ERROR_OUTOFMEMORY); 190 return NULL; 191 } 192 lstrcpyW(target, ca->path); 193 lstrcatW(target, slashW); 194 lstrcatW(target, selectBaseName); 195 196 if (!CopyFileW(catalogFile, target, FALSE)) 197 { 198 HeapFree(GetProcessHeap(), 0, target); 199 return NULL; 200 } 201 SetFileAttributesW(target, FILE_ATTRIBUTE_SYSTEM); 202 203 if (!(ci = HeapAlloc(GetProcessHeap(), 0, sizeof(*ci)))) 204 { 205 HeapFree(GetProcessHeap(), 0, target); 206 SetLastError(ERROR_OUTOFMEMORY); 207 return NULL; 208 } 209 ci->magic = CATINFO_MAGIC; 210 lstrcpyW(ci->file, target); 211 212 HeapFree(GetProcessHeap(), 0, target); 213 return ci; 214 } 215 216 /*********************************************************************** 217 * CryptCATAdminCalcHashFromFileHandle (WINTRUST.@) 218 */ 219 BOOL WINAPI CryptCATAdminCalcHashFromFileHandle(HANDLE hFile, DWORD* pcbHash, 220 BYTE* pbHash, DWORD dwFlags ) 221 { 222 BOOL ret = FALSE; 223 224 TRACE("%p %p %p %x\n", hFile, pcbHash, pbHash, dwFlags); 225 226 if (!hFile || !pcbHash || dwFlags) 227 { 228 SetLastError(ERROR_INVALID_PARAMETER); 229 return FALSE; 230 } 231 if (*pcbHash < 20) 232 { 233 *pcbHash = 20; 234 SetLastError(ERROR_INSUFFICIENT_BUFFER); 235 return TRUE; 236 } 237 238 *pcbHash = 20; 239 if (pbHash) 240 { 241 HCRYPTPROV prov; 242 HCRYPTHASH hash; 243 DWORD bytes_read; 244 BYTE *buffer; 245 246 if (!(buffer = HeapAlloc(GetProcessHeap(), 0, 4096))) 247 { 248 SetLastError(ERROR_OUTOFMEMORY); 249 return FALSE; 250 } 251 ret = CryptAcquireContextW(&prov, NULL, MS_DEF_PROV_W, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT); 252 if (!ret) 253 { 254 HeapFree(GetProcessHeap(), 0, buffer); 255 return FALSE; 256 } 257 ret = CryptCreateHash(prov, CALG_SHA1, 0, 0, &hash); 258 if (!ret) 259 { 260 HeapFree(GetProcessHeap(), 0, buffer); 261 CryptReleaseContext(prov, 0); 262 return FALSE; 263 } 264 while ((ret = ReadFile(hFile, buffer, 4096, &bytes_read, NULL)) && bytes_read) 265 { 266 CryptHashData(hash, buffer, bytes_read, 0); 267 } 268 if (ret) ret = CryptGetHashParam(hash, HP_HASHVAL, pbHash, pcbHash, 0); 269 270 HeapFree(GetProcessHeap(), 0, buffer); 271 CryptDestroyHash(hash); 272 CryptReleaseContext(prov, 0); 273 } 274 return ret; 275 } 276 277 /*********************************************************************** 278 * CryptCATAdminEnumCatalogFromHash (WINTRUST.@) 279 */ 280 HCATINFO WINAPI CryptCATAdminEnumCatalogFromHash(HCATADMIN hCatAdmin, BYTE* pbHash, 281 DWORD cbHash, DWORD dwFlags, 282 HCATINFO* phPrevCatInfo ) 283 { 284 static const WCHAR slashW[] = {'\\',0}; 285 static const WCHAR globW[] = {'\\','*','.','c','a','t',0}; 286 287 struct catadmin *ca = hCatAdmin; 288 WIN32_FIND_DATAW data; 289 HCATINFO prev = NULL; 290 HCRYPTPROV prov; 291 DWORD size; 292 BOOL ret; 293 294 TRACE("%p %p %d %x %p\n", hCatAdmin, pbHash, cbHash, dwFlags, phPrevCatInfo); 295 296 if (!ca || ca->magic != CATADMIN_MAGIC || !pbHash || cbHash != 20 || dwFlags) 297 { 298 SetLastError(ERROR_INVALID_PARAMETER); 299 return NULL; 300 } 301 if (phPrevCatInfo) prev = *phPrevCatInfo; 302 303 ret = CryptAcquireContextW(&prov, NULL, MS_DEF_PROV_W, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT); 304 if (!ret) return NULL; 305 306 if (!prev) 307 { 308 WCHAR *path; 309 310 size = lstrlenW(ca->path) * sizeof(WCHAR) + sizeof(globW); 311 if (!(path = HeapAlloc(GetProcessHeap(), 0, size))) 312 { 313 CryptReleaseContext(prov, 0); 314 SetLastError(ERROR_OUTOFMEMORY); 315 return NULL; 316 } 317 lstrcpyW(path, ca->path); 318 lstrcatW(path, globW); 319 320 FindClose(ca->find); 321 ca->find = FindFirstFileW(path, &data); 322 323 HeapFree(GetProcessHeap(), 0, path); 324 if (ca->find == INVALID_HANDLE_VALUE) 325 { 326 CryptReleaseContext(prov, 0); 327 return NULL; 328 } 329 } 330 else if (!FindNextFileW(ca->find, &data)) 331 { 332 CryptCATAdminReleaseCatalogContext(hCatAdmin, prev, 0); 333 CryptReleaseContext(prov, 0); 334 return NULL; 335 } 336 337 while (1) 338 { 339 WCHAR *filename; 340 CRYPTCATMEMBER *member = NULL; 341 struct catinfo *ci; 342 HANDLE hcat; 343 344 size = (lstrlenW(ca->path) + lstrlenW(data.cFileName) + 2) * sizeof(WCHAR); 345 if (!(filename = HeapAlloc(GetProcessHeap(), 0, size))) 346 { 347 SetLastError(ERROR_OUTOFMEMORY); 348 return NULL; 349 } 350 lstrcpyW(filename, ca->path); 351 lstrcatW(filename, slashW); 352 lstrcatW(filename, data.cFileName); 353 354 hcat = CryptCATOpen(filename, CRYPTCAT_OPEN_EXISTING, prov, 0, 0); 355 if (hcat == INVALID_HANDLE_VALUE) 356 { 357 WARN("couldn't open %s (%u)\n", debugstr_w(filename), GetLastError()); 358 continue; 359 } 360 while ((member = CryptCATEnumerateMember(hcat, member))) 361 { 362 if (member->pIndirectData->Digest.cbData != cbHash) 363 { 364 WARN("amount of hash bytes differs: %u/%u\n", member->pIndirectData->Digest.cbData, cbHash); 365 continue; 366 } 367 if (!memcmp(member->pIndirectData->Digest.pbData, pbHash, cbHash)) 368 { 369 TRACE("file %s matches\n", debugstr_w(data.cFileName)); 370 371 CryptCATClose(hcat); 372 CryptReleaseContext(prov, 0); 373 if (!phPrevCatInfo) 374 { 375 FindClose(ca->find); 376 ca->find = INVALID_HANDLE_VALUE; 377 } 378 ci = create_catinfo(filename); 379 HeapFree(GetProcessHeap(), 0, filename); 380 return ci; 381 } 382 } 383 CryptCATClose(hcat); 384 HeapFree(GetProcessHeap(), 0, filename); 385 386 if (!FindNextFileW(ca->find, &data)) 387 { 388 FindClose(ca->find); 389 ca->find = INVALID_HANDLE_VALUE; 390 CryptReleaseContext(prov, 0); 391 return NULL; 392 } 393 } 394 return NULL; 395 } 396 397 /*********************************************************************** 398 * CryptCATAdminReleaseCatalogContext (WINTRUST.@) 399 * 400 * Release a catalog context handle. 401 * 402 * PARAMS 403 * hCatAdmin [I] Context handle. 404 * hCatInfo [I] Catalog handle. 405 * dwFlags [I] Reserved. 406 * 407 * RETURNS 408 * Success: TRUE. 409 * Failure: FALSE. 410 * 411 */ 412 BOOL WINAPI CryptCATAdminReleaseCatalogContext(HCATADMIN hCatAdmin, 413 HCATINFO hCatInfo, 414 DWORD dwFlags) 415 { 416 struct catinfo *ci = hCatInfo; 417 struct catadmin *ca = hCatAdmin; 418 419 TRACE("%p %p %x\n", hCatAdmin, hCatInfo, dwFlags); 420 421 if (!ca || ca->magic != CATADMIN_MAGIC || !ci || ci->magic != CATINFO_MAGIC) 422 { 423 SetLastError(ERROR_INVALID_PARAMETER); 424 return FALSE; 425 } 426 ci->magic = 0; 427 return HeapFree(GetProcessHeap(), 0, ci); 428 } 429 430 /*********************************************************************** 431 * CryptCATAdminReleaseContext (WINTRUST.@) 432 * 433 * Release a catalog administrator context handle. 434 * 435 * PARAMS 436 * catAdmin [I] Context handle. 437 * dwFlags [I] Reserved. 438 * 439 * RETURNS 440 * Success: TRUE. 441 * Failure: FALSE. 442 * 443 */ 444 BOOL WINAPI CryptCATAdminReleaseContext(HCATADMIN hCatAdmin, DWORD dwFlags ) 445 { 446 struct catadmin *ca = hCatAdmin; 447 448 TRACE("%p %x\n", hCatAdmin, dwFlags); 449 450 if (!ca || ca->magic != CATADMIN_MAGIC) 451 { 452 SetLastError(ERROR_INVALID_PARAMETER); 453 return FALSE; 454 } 455 if (ca->find != INVALID_HANDLE_VALUE) FindClose(ca->find); 456 ca->magic = 0; 457 return HeapFree(GetProcessHeap(), 0, ca); 458 } 459 460 /*********************************************************************** 461 * CryptCATAdminRemoveCatalog (WINTRUST.@) 462 * 463 * Remove a catalog file. 464 * 465 * PARAMS 466 * catAdmin [I] Context handle. 467 * pwszCatalogFile [I] Catalog file. 468 * dwFlags [I] Reserved. 469 * 470 * RETURNS 471 * Success: TRUE. 472 * Failure: FALSE. 473 * 474 */ 475 BOOL WINAPI CryptCATAdminRemoveCatalog(HCATADMIN hCatAdmin, LPCWSTR pwszCatalogFile, DWORD dwFlags) 476 { 477 struct catadmin *ca = hCatAdmin; 478 479 TRACE("%p %s %x\n", hCatAdmin, debugstr_w(pwszCatalogFile), dwFlags); 480 481 if (!ca || ca->magic != CATADMIN_MAGIC) 482 { 483 SetLastError(ERROR_INVALID_PARAMETER); 484 return FALSE; 485 } 486 487 /* Only delete when there is a filename and no path */ 488 if (pwszCatalogFile && pwszCatalogFile[0] != 0 && 489 !wcschr(pwszCatalogFile, '\\') && !wcschr(pwszCatalogFile, '/') && 490 !wcschr(pwszCatalogFile, ':')) 491 { 492 static const WCHAR slashW[] = {'\\',0}; 493 WCHAR *target; 494 DWORD len; 495 496 len = lstrlenW(ca->path) + lstrlenW(pwszCatalogFile) + 2; 497 if (!(target = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR)))) 498 { 499 SetLastError(ERROR_OUTOFMEMORY); 500 return FALSE; 501 } 502 lstrcpyW(target, ca->path); 503 lstrcatW(target, slashW); 504 lstrcatW(target, pwszCatalogFile); 505 506 DeleteFileW(target); 507 508 HeapFree(GetProcessHeap(), 0, target); 509 } 510 511 return TRUE; 512 } 513 514 /*********************************************************************** 515 * CryptCATAdminResolveCatalogPath (WINTRUST.@) 516 */ 517 BOOL WINAPI CryptCATAdminResolveCatalogPath(HCATADMIN hcatadmin, WCHAR *catalog_file, 518 CATALOG_INFO *info, DWORD flags) 519 { 520 static const WCHAR slashW[] = {'\\',0}; 521 struct catadmin *ca = hcatadmin; 522 523 TRACE("%p %s %p %x\n", hcatadmin, debugstr_w(catalog_file), info, flags); 524 525 if (!ca || ca->magic != CATADMIN_MAGIC || !info || info->cbStruct != sizeof(*info) || flags) 526 { 527 SetLastError(ERROR_INVALID_PARAMETER); 528 return FALSE; 529 } 530 lstrcpyW(info->wszCatalogFile, ca->path); 531 lstrcatW(info->wszCatalogFile, slashW); 532 lstrcatW(info->wszCatalogFile, catalog_file); 533 534 return TRUE; 535 } 536 537 /*********************************************************************** 538 * CryptCATClose (WINTRUST.@) 539 */ 540 BOOL WINAPI CryptCATClose(HANDLE hCatalog) 541 { 542 struct cryptcat *cc = hCatalog; 543 544 TRACE("(%p)\n", hCatalog); 545 546 if (!hCatalog || hCatalog == INVALID_HANDLE_VALUE || cc->magic != CRYPTCAT_MAGIC) 547 { 548 SetLastError(ERROR_INVALID_PARAMETER); 549 return FALSE; 550 } 551 HeapFree(GetProcessHeap(), 0, cc->attr); 552 HeapFree(GetProcessHeap(), 0, cc->inner); 553 CryptMsgClose(cc->msg); 554 555 cc->magic = 0; 556 HeapFree(GetProcessHeap(), 0, cc); 557 return TRUE; 558 } 559 560 /*********************************************************************** 561 * CryptCATGetAttrInfo (WINTRUST.@) 562 */ 563 CRYPTCATATTRIBUTE * WINAPI CryptCATGetAttrInfo(HANDLE hCatalog, CRYPTCATMEMBER *member, LPWSTR tag) 564 { 565 struct cryptcat *cc = hCatalog; 566 567 FIXME("%p, %p, %s\n", hCatalog, member, debugstr_w(tag)); 568 569 if (!hCatalog || hCatalog == INVALID_HANDLE_VALUE || cc->magic != CRYPTCAT_MAGIC) 570 { 571 SetLastError(ERROR_INVALID_PARAMETER); 572 return NULL; 573 } 574 SetLastError(CRYPT_E_NOT_FOUND); 575 return NULL; 576 } 577 578 /*********************************************************************** 579 * CryptCATGetCatAttrInfo (WINTRUST.@) 580 */ 581 CRYPTCATATTRIBUTE * WINAPI CryptCATGetCatAttrInfo(HANDLE hCatalog, LPWSTR tag) 582 { 583 struct cryptcat *cc = hCatalog; 584 585 FIXME("%p, %s\n", hCatalog, debugstr_w(tag)); 586 587 if (!hCatalog || hCatalog == INVALID_HANDLE_VALUE || cc->magic != CRYPTCAT_MAGIC) 588 { 589 SetLastError(ERROR_INVALID_PARAMETER); 590 return NULL; 591 } 592 SetLastError(CRYPT_E_NOT_FOUND); 593 return NULL; 594 } 595 596 CRYPTCATMEMBER * WINAPI CryptCATGetMemberInfo(HANDLE hCatalog, LPWSTR tag) 597 { 598 struct cryptcat *cc = hCatalog; 599 600 FIXME("%p, %s\n", hCatalog, debugstr_w(tag)); 601 602 if (!hCatalog || hCatalog == INVALID_HANDLE_VALUE || cc->magic != CRYPTCAT_MAGIC) 603 { 604 SetLastError(ERROR_INVALID_PARAMETER); 605 return NULL; 606 } 607 SetLastError(CRYPT_E_NOT_FOUND); 608 return NULL; 609 } 610 611 /*********************************************************************** 612 * CryptCATEnumerateAttr (WINTRUST.@) 613 */ 614 CRYPTCATATTRIBUTE * WINAPI CryptCATEnumerateAttr(HANDLE hCatalog, CRYPTCATMEMBER *member, CRYPTCATATTRIBUTE *prev) 615 { 616 struct cryptcat *cc = hCatalog; 617 618 FIXME("%p, %p, %p\n", hCatalog, member, prev); 619 620 if (!hCatalog || hCatalog == INVALID_HANDLE_VALUE || cc->magic != CRYPTCAT_MAGIC) 621 { 622 SetLastError(ERROR_INVALID_PARAMETER); 623 return NULL; 624 } 625 SetLastError(CRYPT_E_NOT_FOUND); 626 return NULL; 627 } 628 629 /*********************************************************************** 630 * CryptCATEnumerateCatAttr (WINTRUST.@) 631 */ 632 CRYPTCATATTRIBUTE * WINAPI CryptCATEnumerateCatAttr(HANDLE hCatalog, CRYPTCATATTRIBUTE *prev) 633 { 634 struct cryptcat *cc = hCatalog; 635 636 FIXME("%p, %p\n", hCatalog, prev); 637 638 if (!hCatalog || hCatalog == INVALID_HANDLE_VALUE || cc->magic != CRYPTCAT_MAGIC) 639 { 640 SetLastError(ERROR_INVALID_PARAMETER); 641 return NULL; 642 } 643 SetLastError(CRYPT_E_NOT_FOUND); 644 return NULL; 645 } 646 647 /*********************************************************************** 648 * CryptCATEnumerateMember (WINTRUST.@) 649 */ 650 CRYPTCATMEMBER * WINAPI CryptCATEnumerateMember(HANDLE hCatalog, CRYPTCATMEMBER *prev) 651 { 652 struct cryptcat *cc = hCatalog; 653 CRYPTCATMEMBER *member = prev; 654 CTL_ENTRY *entry; 655 DWORD size, i; 656 657 TRACE("%p, %p\n", hCatalog, prev); 658 659 if (!hCatalog || hCatalog == INVALID_HANDLE_VALUE || cc->magic != CRYPTCAT_MAGIC) 660 { 661 SetLastError(ERROR_INVALID_PARAMETER); 662 return NULL; 663 } 664 665 /* dumping the contents makes me think that dwReserved is the iteration number */ 666 if (!member) 667 { 668 if (!(member = HeapAlloc(GetProcessHeap(), 0, sizeof(*member)))) 669 { 670 SetLastError(ERROR_OUTOFMEMORY); 671 return NULL; 672 } 673 member->cbStruct = sizeof(*member); 674 member->pwszFileName = member->pwszReferenceTag = NULL; 675 member->dwReserved = 0; 676 member->hReserved = NULL; 677 member->gSubjectType = cc->subject; 678 member->fdwMemberFlags = 0; 679 member->pIndirectData = NULL; 680 member->dwCertVersion = cc->inner->dwVersion; 681 } 682 else member->dwReserved++; 683 684 if (member->dwReserved >= cc->inner->cCTLEntry) 685 { 686 SetLastError(ERROR_INVALID_PARAMETER); 687 goto error; 688 } 689 690 /* list them backwards, like native */ 691 entry = &cc->inner->rgCTLEntry[cc->inner->cCTLEntry - member->dwReserved - 1]; 692 693 member->sEncodedIndirectData.cbData = member->sEncodedMemberInfo.cbData = 0; 694 member->sEncodedIndirectData.pbData = member->sEncodedMemberInfo.pbData = NULL; 695 HeapFree(GetProcessHeap(), 0, member->pIndirectData); 696 member->pIndirectData = NULL; 697 698 for (i = 0; i < entry->cAttribute; i++) 699 { 700 CRYPT_ATTRIBUTE *attr = entry->rgAttribute + i; 701 702 if (attr->cValue != 1) 703 { 704 ERR("Can't handle attr->cValue of %u\n", attr->cValue); 705 continue; 706 } 707 if (!strcmp(attr->pszObjId, CAT_MEMBERINFO_OBJID)) 708 { 709 CAT_MEMBERINFO *mi; 710 BOOL ret; 711 712 member->sEncodedMemberInfo.cbData = attr->rgValue->cbData; 713 member->sEncodedMemberInfo.pbData = attr->rgValue->pbData; 714 715 CryptDecodeObject(cc->encoding, CAT_MEMBERINFO_OBJID, attr->rgValue->pbData, attr->rgValue->cbData, 0, NULL, &size); 716 717 if (!(mi = HeapAlloc(GetProcessHeap(), 0, size))) 718 { 719 SetLastError(ERROR_OUTOFMEMORY); 720 goto error; 721 } 722 ret = CryptDecodeObject(cc->encoding, CAT_MEMBERINFO_OBJID, attr->rgValue->pbData, attr->rgValue->cbData, 0, mi, &size); 723 if (ret) 724 { 725 UNICODE_STRING guid; 726 727 member->dwCertVersion = mi->dwCertVersion; 728 RtlInitUnicodeString(&guid, mi->pwszSubjGuid); 729 if (RtlGUIDFromString(&guid, &member->gSubjectType)) 730 { 731 HeapFree(GetProcessHeap(), 0, mi); 732 goto error; 733 } 734 } 735 HeapFree(GetProcessHeap(), 0, mi); 736 if (!ret) goto error; 737 } 738 else if (!strcmp(attr->pszObjId, SPC_INDIRECT_DATA_OBJID)) 739 { 740 /* SPC_INDIRECT_DATA_CONTENT is equal to SIP_INDIRECT_DATA */ 741 742 member->sEncodedIndirectData.cbData = attr->rgValue->cbData; 743 member->sEncodedIndirectData.pbData = attr->rgValue->pbData; 744 745 CryptDecodeObject(cc->encoding, SPC_INDIRECT_DATA_OBJID, attr->rgValue->pbData, attr->rgValue->cbData, 0, NULL, &size); 746 747 if (!(member->pIndirectData = HeapAlloc(GetProcessHeap(), 0, size))) 748 { 749 SetLastError(ERROR_OUTOFMEMORY); 750 goto error; 751 } 752 CryptDecodeObject(cc->encoding, SPC_INDIRECT_DATA_OBJID, attr->rgValue->pbData, attr->rgValue->cbData, 0, member->pIndirectData, &size); 753 } 754 else 755 /* this object id should probably be handled in CryptCATEnumerateAttr */ 756 FIXME("unhandled object id \"%s\"\n", attr->pszObjId); 757 } 758 759 if (!member->sEncodedMemberInfo.cbData || !member->sEncodedIndirectData.cbData) 760 { 761 ERR("Corrupted catalog entry?\n"); 762 SetLastError(CRYPT_E_ATTRIBUTES_MISSING); 763 goto error; 764 } 765 size = (2 * member->pIndirectData->Digest.cbData + 1) * sizeof(WCHAR); 766 if (member->pwszReferenceTag) 767 member->pwszReferenceTag = HeapReAlloc(GetProcessHeap(), 0, member->pwszReferenceTag, size); 768 else 769 member->pwszReferenceTag = HeapAlloc(GetProcessHeap(), 0, size); 770 771 if (!member->pwszReferenceTag) 772 { 773 SetLastError(ERROR_OUTOFMEMORY); 774 goto error; 775 } 776 /* FIXME: reference tag is usually the file hash but doesn't have to be */ 777 for (i = 0; i < member->pIndirectData->Digest.cbData; i++) 778 { 779 DWORD sub; 780 781 sub = member->pIndirectData->Digest.pbData[i] >> 4; 782 member->pwszReferenceTag[i * 2] = (sub < 10 ? '0' + sub : 'A' + sub - 10); 783 sub = member->pIndirectData->Digest.pbData[i] & 0xf; 784 member->pwszReferenceTag[i * 2 + 1] = (sub < 10 ? '0' + sub : 'A' + sub - 10); 785 } 786 member->pwszReferenceTag[i * 2] = 0; 787 return member; 788 789 error: 790 HeapFree(GetProcessHeap(), 0, member->pIndirectData); 791 HeapFree(GetProcessHeap(), 0, member->pwszReferenceTag); 792 HeapFree(GetProcessHeap(), 0, member); 793 return NULL; 794 } 795 796 static CTL_INFO *decode_inner_content(HANDLE hmsg, DWORD encoding, DWORD *len) 797 { 798 DWORD size; 799 LPSTR oid = NULL; 800 BYTE *buffer = NULL; 801 CTL_INFO *inner = NULL; 802 803 if (!CryptMsgGetParam(hmsg, CMSG_INNER_CONTENT_TYPE_PARAM, 0, NULL, &size)) return NULL; 804 if (!(oid = HeapAlloc(GetProcessHeap(), 0, size))) 805 { 806 SetLastError(ERROR_OUTOFMEMORY); 807 return NULL; 808 } 809 if (!CryptMsgGetParam(hmsg, CMSG_INNER_CONTENT_TYPE_PARAM, 0, oid, &size)) goto out; 810 if (!CryptMsgGetParam(hmsg, CMSG_CONTENT_PARAM, 0, NULL, &size)) goto out; 811 if (!(buffer = HeapAlloc(GetProcessHeap(), 0, size))) 812 { 813 SetLastError(ERROR_OUTOFMEMORY); 814 goto out; 815 } 816 if (!CryptMsgGetParam(hmsg, CMSG_CONTENT_PARAM, 0, buffer, &size)) goto out; 817 if (!CryptDecodeObject(encoding, oid, buffer, size, 0, NULL, &size)) goto out; 818 if (!(inner = HeapAlloc(GetProcessHeap(), 0, size))) 819 { 820 SetLastError(ERROR_OUTOFMEMORY); 821 goto out; 822 } 823 if (!CryptDecodeObject(encoding, oid, buffer, size, 0, inner, &size)) goto out; 824 *len = size; 825 826 out: 827 HeapFree(GetProcessHeap(), 0, oid); 828 HeapFree(GetProcessHeap(), 0, buffer); 829 return inner; 830 } 831 832 /*********************************************************************** 833 * CryptCATCatalogInfoFromContext (WINTRUST.@) 834 */ 835 BOOL WINAPI CryptCATCatalogInfoFromContext(HCATINFO hcatinfo, CATALOG_INFO *info, DWORD flags) 836 { 837 struct catinfo *ci = hcatinfo; 838 839 TRACE("%p, %p, %x\n", hcatinfo, info, flags); 840 841 if (!hcatinfo || hcatinfo == INVALID_HANDLE_VALUE || ci->magic != CATINFO_MAGIC || 842 flags || !info || info->cbStruct != sizeof(*info)) 843 { 844 SetLastError(ERROR_INVALID_PARAMETER); 845 return FALSE; 846 } 847 lstrcpyW(info->wszCatalogFile, ci->file); 848 return TRUE; 849 } 850 851 /*********************************************************************** 852 * CryptCATOpen (WINTRUST.@) 853 */ 854 HANDLE WINAPI CryptCATOpen(LPWSTR pwszFileName, DWORD fdwOpenFlags, HCRYPTPROV hProv, 855 DWORD dwPublicVersion, DWORD dwEncodingType) 856 { 857 HANDLE file, hmsg; 858 BYTE *buffer = NULL; 859 DWORD size, flags = OPEN_EXISTING; 860 struct cryptcat *cc; 861 862 TRACE("%s, %x, %lx, %x, %x\n", debugstr_w(pwszFileName), fdwOpenFlags, 863 hProv, dwPublicVersion, dwEncodingType); 864 865 if (!pwszFileName) 866 { 867 SetLastError(ERROR_INVALID_PARAMETER); 868 return INVALID_HANDLE_VALUE; 869 } 870 871 if (!dwEncodingType) dwEncodingType = X509_ASN_ENCODING | PKCS_7_ASN_ENCODING; 872 873 if (fdwOpenFlags & CRYPTCAT_OPEN_ALWAYS) flags |= OPEN_ALWAYS; 874 if (fdwOpenFlags & CRYPTCAT_OPEN_CREATENEW) flags |= CREATE_NEW; 875 876 file = CreateFileW(pwszFileName, GENERIC_READ, FILE_SHARE_READ, NULL, flags, 0, NULL); 877 if (file == INVALID_HANDLE_VALUE) return INVALID_HANDLE_VALUE; 878 879 size = GetFileSize(file, NULL); 880 if (!(buffer = HeapAlloc(GetProcessHeap(), 0, size))) 881 { 882 CloseHandle(file); 883 SetLastError(ERROR_OUTOFMEMORY); 884 return INVALID_HANDLE_VALUE; 885 } 886 if (!(hmsg = CryptMsgOpenToDecode(dwEncodingType, 0, 0, hProv, NULL, NULL))) 887 { 888 CloseHandle(file); 889 HeapFree(GetProcessHeap(), 0, buffer); 890 return INVALID_HANDLE_VALUE; 891 } 892 if (!ReadFile(file, buffer, size, &size, NULL) || !CryptMsgUpdate(hmsg, buffer, size, TRUE)) 893 { 894 CloseHandle(file); 895 HeapFree(GetProcessHeap(), 0, buffer); 896 CryptMsgClose(hmsg); 897 return INVALID_HANDLE_VALUE; 898 } 899 HeapFree(GetProcessHeap(), 0, buffer); 900 CloseHandle(file); 901 902 size = sizeof(DWORD); 903 if (!(cc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*cc)))) 904 { 905 CryptMsgClose(hmsg); 906 SetLastError(ERROR_OUTOFMEMORY); 907 return INVALID_HANDLE_VALUE; 908 } 909 910 cc->msg = hmsg; 911 cc->encoding = dwEncodingType; 912 if (CryptMsgGetParam(hmsg, CMSG_ATTR_CERT_COUNT_PARAM, 0, &cc->attr_count, &size)) 913 { 914 DWORD i, sum = 0; 915 BYTE *p; 916 917 for (i = 0; i < cc->attr_count; i++) 918 { 919 if (!CryptMsgGetParam(hmsg, CMSG_ATTR_CERT_PARAM, i, NULL, &size)) 920 { 921 CryptMsgClose(hmsg); 922 HeapFree(GetProcessHeap(), 0, cc); 923 return INVALID_HANDLE_VALUE; 924 } 925 sum += size; 926 } 927 if (!(cc->attr = HeapAlloc(GetProcessHeap(), 0, sizeof(*cc->attr) * cc->attr_count + sum))) 928 { 929 CryptMsgClose(hmsg); 930 HeapFree(GetProcessHeap(), 0, cc); 931 SetLastError(ERROR_OUTOFMEMORY); 932 return INVALID_HANDLE_VALUE; 933 } 934 p = (BYTE *)(cc->attr + cc->attr_count); 935 for (i = 0; i < cc->attr_count; i++) 936 { 937 if (!CryptMsgGetParam(hmsg, CMSG_ATTR_CERT_PARAM, i, NULL, &size)) 938 { 939 CryptMsgClose(hmsg); 940 HeapFree(GetProcessHeap(), 0, cc->attr); 941 HeapFree(GetProcessHeap(), 0, cc); 942 return INVALID_HANDLE_VALUE; 943 } 944 if (!CryptMsgGetParam(hmsg, CMSG_ATTR_CERT_PARAM, i, p, &size)) 945 { 946 CryptMsgClose(hmsg); 947 HeapFree(GetProcessHeap(), 0, cc->attr); 948 HeapFree(GetProcessHeap(), 0, cc); 949 return INVALID_HANDLE_VALUE; 950 } 951 p += size; 952 } 953 cc->inner = decode_inner_content(hmsg, dwEncodingType, &cc->inner_len); 954 if (!cc->inner || !CryptSIPRetrieveSubjectGuid(pwszFileName, NULL, &cc->subject)) 955 { 956 CryptMsgClose(hmsg); 957 HeapFree(GetProcessHeap(), 0, cc->attr); 958 HeapFree(GetProcessHeap(), 0, cc->inner); 959 HeapFree(GetProcessHeap(), 0, cc); 960 return INVALID_HANDLE_VALUE; 961 } 962 cc->magic = CRYPTCAT_MAGIC; 963 return cc; 964 } 965 HeapFree(GetProcessHeap(), 0, cc); 966 return INVALID_HANDLE_VALUE; 967 } 968 969 /*********************************************************************** 970 * CryptSIPCreateIndirectData (WINTRUST.@) 971 */ 972 BOOL WINAPI CryptSIPCreateIndirectData(SIP_SUBJECTINFO* pSubjectInfo, DWORD* pcbIndirectData, 973 SIP_INDIRECT_DATA* pIndirectData) 974 { 975 FIXME("(%p %p %p) stub\n", pSubjectInfo, pcbIndirectData, pIndirectData); 976 977 return FALSE; 978 } 979 980 981 /*********************************************************************** 982 * CryptCATCDFClose (WINTRUST.@) 983 */ 984 BOOL WINAPI CryptCATCDFClose(CRYPTCATCDF *pCDF) 985 { 986 FIXME("(%p) stub\n", pCDF); 987 988 return FALSE; 989 } 990 991 /*********************************************************************** 992 * CryptCATCDFEnumCatAttributes (WINTRUST.@) 993 */ 994 CRYPTCATATTRIBUTE * WINAPI CryptCATCDFEnumCatAttributes(CRYPTCATCDF *pCDF, 995 CRYPTCATATTRIBUTE *pPrevAttr, 996 PFN_CDF_PARSE_ERROR_CALLBACK pfnParseError) 997 { 998 FIXME("(%p %p %p) stub\n", pCDF, pPrevAttr, pfnParseError); 999 1000 return NULL; 1001 } 1002 1003 /*********************************************************************** 1004 * CryptCATCDFEnumMembersByCDFTagEx (WINTRUST.@) 1005 */ 1006 LPWSTR WINAPI CryptCATCDFEnumMembersByCDFTagEx(CRYPTCATCDF *pCDF, LPWSTR pwszPrevCDFTag, 1007 PFN_CDF_PARSE_ERROR_CALLBACK pfnParseError, 1008 CRYPTCATMEMBER **ppMember, BOOL fContinueOnError, 1009 LPVOID pvReserved) 1010 { 1011 FIXME("(%p %s %p %p %d %p) stub\n", pCDF, debugstr_w(pwszPrevCDFTag), pfnParseError, 1012 ppMember, fContinueOnError, pvReserved); 1013 1014 return NULL; 1015 } 1016 1017 /*********************************************************************** 1018 * CryptCATCDFOpen (WINTRUST.@) 1019 */ 1020 CRYPTCATCDF * WINAPI CryptCATCDFOpen(LPWSTR pwszFilePath, 1021 PFN_CDF_PARSE_ERROR_CALLBACK pfnParseError) 1022 { 1023 FIXME("(%s %p) stub\n", debugstr_w(pwszFilePath), pfnParseError); 1024 1025 return NULL; 1026 } 1027 1028 static BOOL WINTRUST_GetSignedMsgFromPEFile(SIP_SUBJECTINFO *pSubjectInfo, 1029 DWORD *pdwEncodingType, DWORD dwIndex, DWORD *pcbSignedDataMsg, 1030 BYTE *pbSignedDataMsg) 1031 { 1032 BOOL ret; 1033 WIN_CERTIFICATE *pCert = NULL; 1034 HANDLE file; 1035 1036 TRACE("(%p %p %d %p %p)\n", pSubjectInfo, pdwEncodingType, dwIndex, 1037 pcbSignedDataMsg, pbSignedDataMsg); 1038 1039 if(pSubjectInfo->hFile && pSubjectInfo->hFile!=INVALID_HANDLE_VALUE) 1040 file = pSubjectInfo->hFile; 1041 else 1042 { 1043 file = CreateFileW(pSubjectInfo->pwsFileName, GENERIC_READ, 1044 FILE_SHARE_READ|FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, NULL); 1045 if(file == INVALID_HANDLE_VALUE) 1046 return FALSE; 1047 } 1048 1049 if (!pbSignedDataMsg) 1050 { 1051 WIN_CERTIFICATE cert; 1052 1053 /* app hasn't passed buffer, just get the length */ 1054 ret = ImageGetCertificateHeader(file, dwIndex, &cert); 1055 if (ret) 1056 { 1057 switch (cert.wCertificateType) 1058 { 1059 case WIN_CERT_TYPE_X509: 1060 case WIN_CERT_TYPE_PKCS_SIGNED_DATA: 1061 *pcbSignedDataMsg = cert.dwLength; 1062 break; 1063 default: 1064 WARN("unknown certificate type %d\n", cert.wCertificateType); 1065 ret = FALSE; 1066 } 1067 } 1068 } 1069 else 1070 { 1071 DWORD len = 0; 1072 1073 ret = ImageGetCertificateData(file, dwIndex, NULL, &len); 1074 if (GetLastError() != ERROR_INSUFFICIENT_BUFFER) 1075 goto error; 1076 pCert = HeapAlloc(GetProcessHeap(), 0, len); 1077 if (!pCert) 1078 { 1079 ret = FALSE; 1080 goto error; 1081 } 1082 ret = ImageGetCertificateData(file, dwIndex, pCert, &len); 1083 if (!ret) 1084 goto error; 1085 pCert->dwLength -= FIELD_OFFSET(WIN_CERTIFICATE, bCertificate); 1086 if (*pcbSignedDataMsg < pCert->dwLength) 1087 { 1088 *pcbSignedDataMsg = pCert->dwLength; 1089 SetLastError(ERROR_INSUFFICIENT_BUFFER); 1090 ret = FALSE; 1091 } 1092 else 1093 { 1094 memcpy(pbSignedDataMsg, pCert->bCertificate, pCert->dwLength); 1095 *pcbSignedDataMsg = pCert->dwLength; 1096 switch (pCert->wCertificateType) 1097 { 1098 case WIN_CERT_TYPE_X509: 1099 *pdwEncodingType = X509_ASN_ENCODING; 1100 break; 1101 case WIN_CERT_TYPE_PKCS_SIGNED_DATA: 1102 *pdwEncodingType = X509_ASN_ENCODING | PKCS_7_ASN_ENCODING; 1103 break; 1104 default: 1105 WARN("don't know what to do for encoding type %d\n", 1106 pCert->wCertificateType); 1107 *pdwEncodingType = 0; 1108 ret = FALSE; 1109 } 1110 } 1111 } 1112 error: 1113 if(pSubjectInfo->hFile != file) 1114 CloseHandle(file); 1115 HeapFree(GetProcessHeap(), 0, pCert); 1116 return ret; 1117 } 1118 1119 static BOOL WINTRUST_PutSignedMsgToPEFile(SIP_SUBJECTINFO* pSubjectInfo, DWORD pdwEncodingType, 1120 DWORD* pdwIndex, DWORD cbSignedDataMsg, BYTE* pbSignedDataMsg) 1121 { 1122 WIN_CERTIFICATE *cert; 1123 HANDLE file; 1124 DWORD size; 1125 BOOL ret; 1126 1127 if(pSubjectInfo->hFile && pSubjectInfo->hFile!=INVALID_HANDLE_VALUE) 1128 file = pSubjectInfo->hFile; 1129 else 1130 { 1131 file = CreateFileW(pSubjectInfo->pwsFileName, GENERIC_READ|GENERIC_WRITE, 1132 FILE_SHARE_READ|FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, NULL); 1133 if(file == INVALID_HANDLE_VALUE) 1134 return FALSE; 1135 } 1136 1137 /* int aligned WIN_CERTIFICATE structure with cbSignedDataMsg+1 bytes of data */ 1138 size = FIELD_OFFSET(WIN_CERTIFICATE, bCertificate[cbSignedDataMsg+4]) & (~3); 1139 cert = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, size); 1140 if(!cert) 1141 return FALSE; 1142 1143 cert->dwLength = size; 1144 cert->wRevision = WIN_CERT_REVISION_2_0; 1145 cert->wCertificateType = WIN_CERT_TYPE_PKCS_SIGNED_DATA; 1146 memcpy(cert->bCertificate, pbSignedDataMsg, cbSignedDataMsg); 1147 ret = ImageAddCertificate(file, cert, pdwIndex); 1148 1149 HeapFree(GetProcessHeap(), 0, cert); 1150 if(file != pSubjectInfo->hFile) 1151 CloseHandle(file); 1152 return ret; 1153 } 1154 1155 /* structure offsets */ 1156 #define cfhead_Signature (0x00) 1157 #define cfhead_CabinetSize (0x08) 1158 #define cfhead_MinorVersion (0x18) 1159 #define cfhead_MajorVersion (0x19) 1160 #define cfhead_Flags (0x1E) 1161 #define cfhead_SIZEOF (0x24) 1162 #define cfheadext_HeaderReserved (0x00) 1163 #define cfheadext_SIZEOF (0x04) 1164 #define cfsigninfo_CertOffset (0x04) 1165 #define cfsigninfo_CertSize (0x08) 1166 #define cfsigninfo_SIZEOF (0x0C) 1167 1168 /* flags */ 1169 #define cfheadRESERVE_PRESENT (0x0004) 1170 1171 /* endian-neutral reading of little-endian data */ 1172 #define EndGetI32(a) ((((a)[3])<<24)|(((a)[2])<<16)|(((a)[1])<<8)|((a)[0])) 1173 #define EndGetI16(a) ((((a)[1])<<8)|((a)[0])) 1174 1175 /* For documentation purposes only: this is the structure in the reserved 1176 * area of a signed cabinet file. The cert offset indicates where in the 1177 * cabinet file the signature resides, and the count indicates its size. 1178 */ 1179 typedef struct _CAB_SIGNINFO 1180 { 1181 WORD unk0; /* always 0? */ 1182 WORD unk1; /* always 0x0010? */ 1183 DWORD dwCertOffset; 1184 DWORD cbCertBlock; 1185 } CAB_SIGNINFO, *PCAB_SIGNINFO; 1186 1187 static BOOL WINTRUST_GetSignedMsgFromCabFile(SIP_SUBJECTINFO *pSubjectInfo, 1188 DWORD *pdwEncodingType, DWORD dwIndex, DWORD *pcbSignedDataMsg, 1189 BYTE *pbSignedDataMsg) 1190 { 1191 int header_resv; 1192 LONG base_offset, cabsize; 1193 USHORT flags; 1194 BYTE buf[64]; 1195 DWORD cert_offset, cert_size, dwRead; 1196 1197 TRACE("(%p %p %d %p %p)\n", pSubjectInfo, pdwEncodingType, dwIndex, 1198 pcbSignedDataMsg, pbSignedDataMsg); 1199 1200 /* get basic offset & size info */ 1201 base_offset = SetFilePointer(pSubjectInfo->hFile, 0L, NULL, SEEK_CUR); 1202 1203 if (SetFilePointer(pSubjectInfo->hFile, 0, NULL, SEEK_END) == INVALID_SET_FILE_POINTER) 1204 { 1205 TRACE("seek error\n"); 1206 return FALSE; 1207 } 1208 1209 cabsize = SetFilePointer(pSubjectInfo->hFile, 0L, NULL, SEEK_CUR); 1210 if ((cabsize == -1) || (base_offset == -1) || 1211 (SetFilePointer(pSubjectInfo->hFile, 0, NULL, SEEK_SET) == INVALID_SET_FILE_POINTER)) 1212 { 1213 TRACE("seek error\n"); 1214 return FALSE; 1215 } 1216 1217 /* read in the CFHEADER */ 1218 if (!ReadFile(pSubjectInfo->hFile, buf, cfhead_SIZEOF, &dwRead, NULL) || 1219 dwRead != cfhead_SIZEOF) 1220 { 1221 TRACE("reading header failed\n"); 1222 return FALSE; 1223 } 1224 1225 /* check basic MSCF signature */ 1226 if (EndGetI32(buf+cfhead_Signature) != 0x4643534d) 1227 { 1228 WARN("cabinet signature not present\n"); 1229 return FALSE; 1230 } 1231 1232 /* Ignore the number of folders and files and the set and cabinet IDs */ 1233 1234 /* check the header revision */ 1235 if ((buf[cfhead_MajorVersion] > 1) || 1236 (buf[cfhead_MajorVersion] == 1 && buf[cfhead_MinorVersion] > 3)) 1237 { 1238 WARN("cabinet format version > 1.3\n"); 1239 return FALSE; 1240 } 1241 1242 /* pull the flags out */ 1243 flags = EndGetI16(buf+cfhead_Flags); 1244 1245 if (!(flags & cfheadRESERVE_PRESENT)) 1246 { 1247 TRACE("no header present, not signed\n"); 1248 return FALSE; 1249 } 1250 1251 if (!ReadFile(pSubjectInfo->hFile, buf, cfheadext_SIZEOF, &dwRead, NULL) || 1252 dwRead != cfheadext_SIZEOF) 1253 { 1254 ERR("bunk reserve-sizes?\n"); 1255 return FALSE; 1256 } 1257 1258 header_resv = EndGetI16(buf+cfheadext_HeaderReserved); 1259 if (!header_resv) 1260 { 1261 TRACE("no header_resv, not signed\n"); 1262 return FALSE; 1263 } 1264 else if (header_resv < cfsigninfo_SIZEOF) 1265 { 1266 TRACE("header_resv too small, not signed\n"); 1267 return FALSE; 1268 } 1269 1270 if (header_resv > 60000) 1271 { 1272 WARN("WARNING; header reserved space > 60000\n"); 1273 } 1274 1275 if (!ReadFile(pSubjectInfo->hFile, buf, cfsigninfo_SIZEOF, &dwRead, NULL) || 1276 dwRead != cfsigninfo_SIZEOF) 1277 { 1278 ERR("couldn't read reserve\n"); 1279 return FALSE; 1280 } 1281 1282 cert_offset = EndGetI32(buf+cfsigninfo_CertOffset); 1283 TRACE("cert_offset: %d\n", cert_offset); 1284 cert_size = EndGetI32(buf+cfsigninfo_CertSize); 1285 TRACE("cert_size: %d\n", cert_size); 1286 1287 /* The redundant checks are to avoid wraparound */ 1288 if (cert_offset > cabsize || cert_size > cabsize || 1289 cert_offset + cert_size > cabsize) 1290 { 1291 WARN("offset beyond file, not attempting to read\n"); 1292 return FALSE; 1293 } 1294 1295 SetFilePointer(pSubjectInfo->hFile, base_offset, NULL, SEEK_SET); 1296 if (!pbSignedDataMsg) 1297 { 1298 *pcbSignedDataMsg = cert_size; 1299 return TRUE; 1300 } 1301 if (*pcbSignedDataMsg < cert_size) 1302 { 1303 *pcbSignedDataMsg = cert_size; 1304 SetLastError(ERROR_INSUFFICIENT_BUFFER); 1305 return FALSE; 1306 } 1307 if (SetFilePointer(pSubjectInfo->hFile, cert_offset, NULL, SEEK_SET) == INVALID_SET_FILE_POINTER) 1308 { 1309 ERR("couldn't seek to cert location\n"); 1310 return FALSE; 1311 } 1312 if (!ReadFile(pSubjectInfo->hFile, pbSignedDataMsg, cert_size, &dwRead, 1313 NULL) || dwRead != cert_size) 1314 { 1315 ERR("couldn't read cert\n"); 1316 SetFilePointer(pSubjectInfo->hFile, base_offset, NULL, SEEK_SET); 1317 return FALSE; 1318 } 1319 /* The encoding of the files I've seen appears to be in ASN.1 1320 * format, and there isn't a field indicating the type, so assume it 1321 * always is. 1322 */ 1323 *pdwEncodingType = X509_ASN_ENCODING | PKCS_7_ASN_ENCODING; 1324 /* Restore base offset */ 1325 SetFilePointer(pSubjectInfo->hFile, base_offset, NULL, SEEK_SET); 1326 return TRUE; 1327 } 1328 1329 static BOOL WINTRUST_GetSignedMsgFromCatFile(SIP_SUBJECTINFO *pSubjectInfo, 1330 DWORD *pdwEncodingType, DWORD dwIndex, DWORD *pcbSignedDataMsg, 1331 BYTE *pbSignedDataMsg) 1332 { 1333 BOOL ret; 1334 1335 TRACE("(%p %p %d %p %p)\n", pSubjectInfo, pdwEncodingType, dwIndex, 1336 pcbSignedDataMsg, pbSignedDataMsg); 1337 1338 if (!pbSignedDataMsg) 1339 { 1340 *pcbSignedDataMsg = GetFileSize(pSubjectInfo->hFile, NULL); 1341 ret = TRUE; 1342 } 1343 else 1344 { 1345 DWORD len = GetFileSize(pSubjectInfo->hFile, NULL); 1346 1347 if (*pcbSignedDataMsg < len) 1348 { 1349 *pcbSignedDataMsg = len; 1350 SetLastError(ERROR_INSUFFICIENT_BUFFER); 1351 ret = FALSE; 1352 } 1353 else 1354 { 1355 ret = ReadFile(pSubjectInfo->hFile, pbSignedDataMsg, len, 1356 pcbSignedDataMsg, NULL); 1357 if (ret) 1358 *pdwEncodingType = X509_ASN_ENCODING | PKCS_7_ASN_ENCODING; 1359 } 1360 } 1361 return ret; 1362 } 1363 1364 /* GUIDs used by CryptSIPGetSignedDataMsg and CryptSIPPutSignedDataMsg */ 1365 static const GUID unknown = { 0xC689AAB8, 0x8E78, 0x11D0, { 0x8C,0x47, 1366 0x00,0xC0,0x4F,0xC2,0x95,0xEE } }; 1367 static const GUID cabGUID = { 0xC689AABA, 0x8E78, 0x11D0, { 0x8C,0x47, 1368 0x00,0xC0,0x4F,0xC2,0x95,0xEE } }; 1369 static const GUID catGUID = { 0xDE351A43, 0x8E59, 0x11D0, { 0x8C,0x47, 1370 0x00,0xC0,0x4F,0xC2,0x95,0xEE }}; 1371 1372 /*********************************************************************** 1373 * CryptSIPGetSignedDataMsg (WINTRUST.@) 1374 */ 1375 BOOL WINAPI CryptSIPGetSignedDataMsg(SIP_SUBJECTINFO* pSubjectInfo, DWORD* pdwEncodingType, 1376 DWORD dwIndex, DWORD* pcbSignedDataMsg, BYTE* pbSignedDataMsg) 1377 { 1378 BOOL ret; 1379 1380 TRACE("(%p %p %d %p %p)\n", pSubjectInfo, pdwEncodingType, dwIndex, 1381 pcbSignedDataMsg, pbSignedDataMsg); 1382 1383 if(!pSubjectInfo) 1384 { 1385 SetLastError(ERROR_INVALID_PARAMETER); 1386 return FALSE; 1387 } 1388 1389 if (!memcmp(pSubjectInfo->pgSubjectType, &unknown, sizeof(unknown))) 1390 ret = WINTRUST_GetSignedMsgFromPEFile(pSubjectInfo, pdwEncodingType, 1391 dwIndex, pcbSignedDataMsg, pbSignedDataMsg); 1392 else if (!memcmp(pSubjectInfo->pgSubjectType, &cabGUID, sizeof(cabGUID))) 1393 ret = WINTRUST_GetSignedMsgFromCabFile(pSubjectInfo, pdwEncodingType, 1394 dwIndex, pcbSignedDataMsg, pbSignedDataMsg); 1395 else if (!memcmp(pSubjectInfo->pgSubjectType, &catGUID, sizeof(catGUID))) 1396 ret = WINTRUST_GetSignedMsgFromCatFile(pSubjectInfo, pdwEncodingType, 1397 dwIndex, pcbSignedDataMsg, pbSignedDataMsg); 1398 else 1399 { 1400 FIXME("unimplemented for subject type %s\n", 1401 debugstr_guid(pSubjectInfo->pgSubjectType)); 1402 ret = FALSE; 1403 } 1404 1405 TRACE("returning %d\n", ret); 1406 return ret; 1407 } 1408 1409 /*********************************************************************** 1410 * CryptSIPPutSignedDataMsg (WINTRUST.@) 1411 */ 1412 BOOL WINAPI CryptSIPPutSignedDataMsg(SIP_SUBJECTINFO* pSubjectInfo, DWORD pdwEncodingType, 1413 DWORD* pdwIndex, DWORD cbSignedDataMsg, BYTE* pbSignedDataMsg) 1414 { 1415 TRACE("(%p %d %p %d %p)\n", pSubjectInfo, pdwEncodingType, pdwIndex, 1416 cbSignedDataMsg, pbSignedDataMsg); 1417 1418 if(!pSubjectInfo) { 1419 SetLastError(ERROR_INVALID_PARAMETER); 1420 return FALSE; 1421 } 1422 1423 if(!memcmp(pSubjectInfo->pgSubjectType, &unknown, sizeof(unknown))) 1424 return WINTRUST_PutSignedMsgToPEFile(pSubjectInfo, pdwEncodingType, 1425 pdwIndex, cbSignedDataMsg, pbSignedDataMsg); 1426 else 1427 FIXME("unimplemented for subject type %s\n", 1428 debugstr_guid(pSubjectInfo->pgSubjectType)); 1429 1430 return FALSE; 1431 } 1432 1433 /*********************************************************************** 1434 * CryptSIPRemoveSignedDataMsg (WINTRUST.@) 1435 */ 1436 BOOL WINAPI CryptSIPRemoveSignedDataMsg(SIP_SUBJECTINFO* pSubjectInfo, 1437 DWORD dwIndex) 1438 { 1439 FIXME("(%p %d) stub\n", pSubjectInfo, dwIndex); 1440 1441 return FALSE; 1442 } 1443 1444 /*********************************************************************** 1445 * CryptSIPVerifyIndirectData (WINTRUST.@) 1446 */ 1447 BOOL WINAPI CryptSIPVerifyIndirectData(SIP_SUBJECTINFO* pSubjectInfo, 1448 SIP_INDIRECT_DATA* pIndirectData) 1449 { 1450 FIXME("(%p %p) stub\n", pSubjectInfo, pIndirectData); 1451 1452 return FALSE; 1453 } 1454