Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

808 lines
22 KiB

  1. /*++
  2. Copyright (c) Microsoft Corporation
  3. Module Name:
  4. strongname.cpp
  5. Abstract:
  6. Fusion Win32 implementation of the Fusion URT strong-name stuff
  7. Author:
  8. Jon Wiswall (jonwis) 11-October-2000
  9. Revision History:
  10. jonwis/7-November-2000: Added ability to find a strong name from a
  11. certificate context structure, as well as the ability to scan
  12. a catalog for strong names. Also changed the way strong names
  13. are generated from a public key to be identically in-line with
  14. Fusion URT.
  15. --*/
  16. #include "stdinc.h"
  17. #include "wincrypt.h"
  18. #include "fusionbuffer.h"
  19. #include "strongname.h"
  20. #include "hashfile.h"
  21. #include "sxsp.h"
  22. BOOL
  23. SxspHashStringToBytes(
  24. PCWSTR hsHashString,
  25. SIZE_T cchHashString,
  26. CFusionArray<BYTE> &OutputBuffer
  27. )
  28. {
  29. //
  30. // 2 here is not sizeof(WCHAR) it is how many digits a byte takes to print (or be scanned from,
  31. // as is actually happening here)
  32. //
  33. DWORD dwByteCount = static_cast<DWORD>(cchHashString) / 2;
  34. DWORD dwIdx = 0;
  35. int iHi, iLo;
  36. BOOL bSuccess = FALSE;
  37. FN_TRACE_WIN32(bSuccess);
  38. //
  39. // We look on odd numbers with disdain.
  40. //
  41. PARAMETER_CHECK((cchHashString % 2) == 0);
  42. if ( OutputBuffer.GetSize() != dwByteCount )
  43. {
  44. IFW32FALSE_EXIT(OutputBuffer.Win32SetSize(dwByteCount, CFusionArray<BYTE>::eSetSizeModeExact));
  45. }
  46. //
  47. // Sneak through the list of characters and turn them into the
  48. // hi and lo nibbles per byte position, then write them into the
  49. // output buffer.
  50. //
  51. for (DWORD i = 0; (i < cchHashString) && (dwIdx < OutputBuffer.GetSize()); i += 2)
  52. {
  53. if (((iHi = SxspHexDigitToValue(hsHashString[i])) >= 0) &&
  54. ((iLo = SxspHexDigitToValue(hsHashString[i+1])) >= 0))
  55. {
  56. OutputBuffer[dwIdx++] = static_cast<BYTE>(((iHi & 0xF) << 4) | (iLo & 0xF));
  57. }
  58. else
  59. {
  60. // Something bad happened while trying to read from the string,
  61. // maybe it contained invalid values?
  62. goto Exit;
  63. }
  64. }
  65. bSuccess = TRUE;
  66. Exit:
  67. return bSuccess;
  68. }
  69. inline VOID
  70. pReverseByteString(PBYTE pbBytes, SIZE_T cbBytes)
  71. {
  72. SIZE_T index = 0;
  73. if (cbBytes-- == 0) return;
  74. while (index < cbBytes)
  75. {
  76. BYTE bLeft = pbBytes[index];
  77. BYTE bRight = pbBytes[cbBytes];
  78. pbBytes[index++] = bRight;
  79. pbBytes[cbBytes--] = bLeft;
  80. }
  81. }
  82. BOOL
  83. SxspHashBytesToString(
  84. IN const BYTE* pbSource,
  85. IN SIZE_T cbSource,
  86. OUT CBaseStringBuffer &sbDestination
  87. )
  88. {
  89. BOOL bSuccess = FALSE;
  90. DWORD i;
  91. PWSTR pwsCursor;
  92. const static WCHAR HexCharList[] = L"0123456789abcdef";
  93. CStringBufferAccessor Accessor;
  94. FN_TRACE_WIN32(bSuccess);
  95. sbDestination.Clear();
  96. IFW32FALSE_EXIT(sbDestination.Win32ResizeBuffer((cbSource + 1) * 2, eDoNotPreserveBufferContents));
  97. Accessor.Attach(&sbDestination);
  98. pwsCursor = Accessor;
  99. for (i = 0; i < cbSource; i++)
  100. {
  101. pwsCursor[i*2] = HexCharList[ (pbSource[i] >> 4) & 0x0F ];
  102. pwsCursor[i*2+1] = HexCharList[ pbSource[i] & 0x0F ];
  103. }
  104. //
  105. // Because of the way string accessors and clear works, we have to clip off
  106. // the rest by a null character. Odd, but it works.
  107. //
  108. pwsCursor[i*2] = L'\0';
  109. bSuccess = TRUE;
  110. Exit:
  111. return bSuccess;
  112. }
  113. BOOL
  114. SxspGetStrongNameOfKey(
  115. IN const CFusionArray<BYTE> &PublicKeyBits,
  116. OUT CFusionArray<BYTE> &StrongNameBits
  117. )
  118. /*++
  119. Note to posterity:
  120. This implementation has been blessed by the Fusion URT people to be identically
  121. in synch with their implementation. Do _not_ change anything here unless you're
  122. really sure there's a bug or there's a change in spec. The basic operation of this
  123. is as follows:
  124. - Get crypto provider
  125. - Create a SHA1 hash object from the crypto stuff
  126. - Hash the data
  127. - Extract the hash data into the output buffer
  128. - Move the low order 8-bytes of the hash (bytes 11 through 19) down to 0-7
  129. - Reverse the bytes to obtain a "network ordered" 64-bit string
  130. The last two steps are the important thing - work with Rudi Martin (Fusion URT)
  131. if you think there's a better way.
  132. --*/
  133. {
  134. FN_PROLOG_WIN32
  135. CFusionHash hHash;
  136. PSXS_PUBLIC_KEY_INFO pPubKeyInfo;
  137. PARAMETER_CHECK(PublicKeyBits.GetSize() >= sizeof(*pPubKeyInfo));
  138. if (StrongNameBits.GetSize() < STRONG_NAME_BYTE_LENGTH)
  139. {
  140. IFW32FALSE_EXIT(StrongNameBits.Win32SetSize(STRONG_NAME_BYTE_LENGTH, CFusionArray<BYTE>::eSetSizeModeExact));
  141. }
  142. //
  143. // Convert our pointer back for a second - it's a persisted version of this
  144. // structure anyhow.
  145. //
  146. pPubKeyInfo = (PSXS_PUBLIC_KEY_INFO)PublicKeyBits.GetArrayPtr();
  147. //
  148. // Make ourselves a hash object.
  149. //
  150. IFW32FALSE_EXIT(hHash.Win32Initialize(CALG_SHA1));
  151. //
  152. // Hash the actual data that we were passed in to generate the strong name.
  153. //
  154. IFW32FALSE_EXIT(
  155. hHash.Win32HashData(
  156. PublicKeyBits.GetArrayPtr(),
  157. PublicKeyBits.GetSize()));
  158. //
  159. // Find out how big the hash data really is from what was hashed.
  160. //
  161. IFW32FALSE_EXIT(hHash.Win32GetValue(StrongNameBits));
  162. // NTRAID#NTBUG9 - 587802 - 2002/03/26 - xiaoyuw:
  163. // I think we need add one line,
  164. // StrongNameBits.GetSize() > STRONG_NAME_BYTE_LENGTH)
  165. // before calling into the following code. although rtlMoveMemory dealt with overlap,
  166. // it does not make sense if there is really an overlap.
  167. //
  168. // Move the last eight bytes of the hash downwards using memmove, because
  169. // it knows about things like overlapping blocks.
  170. //
  171. PBYTE pbBits = static_cast<PBYTE>(StrongNameBits.GetArrayPtr());
  172. INTERNAL_ERROR_CHECK(StrongNameBits.GetSize() >= STRONG_NAME_BYTE_LENGTH);
  173. ::RtlMoveMemory(
  174. pbBits,
  175. pbBits + (StrongNameBits.GetSize() - STRONG_NAME_BYTE_LENGTH),
  176. STRONG_NAME_BYTE_LENGTH);
  177. pReverseByteString(pbBits, STRONG_NAME_BYTE_LENGTH);
  178. IFW32FALSE_EXIT(StrongNameBits.Win32SetSize(STRONG_NAME_BYTE_LENGTH, CFusionArray<BYTE>::eSetSizeModeExact));
  179. FN_EPILOG
  180. }
  181. BOOL
  182. SxspDoesStrongNameMatchKey(
  183. IN const CBaseStringBuffer &rbuffKeyString,
  184. IN const CBaseStringBuffer &rbuffStrongNameString,
  185. OUT BOOL &rfKeyMatchesStrongName
  186. )
  187. {
  188. FN_PROLOG_WIN32
  189. CSmallStringBuffer buffStrongNameCandidate;
  190. PARAMETER_CHECK(::SxspIsFullHexString(rbuffKeyString, rbuffKeyString.Cch()));
  191. PARAMETER_CHECK(::SxspIsFullHexString(rbuffStrongNameString, rbuffStrongNameString.Cch()));
  192. //
  193. // Convert the key over to its corresponding strong name
  194. //
  195. IFW32FALSE_EXIT(::SxspGetStrongNameOfKey(rbuffKeyString, buffStrongNameCandidate));
  196. //
  197. // And compare what the caller thinks it should be.
  198. //
  199. rfKeyMatchesStrongName = (::FusionpCompareStrings(
  200. rbuffStrongNameString,
  201. rbuffStrongNameString.Cch(),
  202. buffStrongNameCandidate,
  203. buffStrongNameCandidate.Cch(),
  204. false) == 0);
  205. FN_EPILOG
  206. }
  207. BOOL
  208. SxspGetStrongNameOfKey(
  209. IN const CBaseStringBuffer &rbuffKeyString,
  210. OUT CBaseStringBuffer &sbStrongName
  211. )
  212. {
  213. CFusionArray<BYTE> KeyBytes, StrongNameBytes;
  214. BOOL bSuccess = FALSE;
  215. FN_TRACE_WIN32(bSuccess);
  216. //
  217. // Convert the string to bytes, generate the strong name, convert back to
  218. // a string.
  219. //
  220. IFW32FALSE_EXIT(::SxspHashStringToBytes(rbuffKeyString, rbuffKeyString.Cch(), KeyBytes));
  221. IFW32FALSE_EXIT(::SxspGetStrongNameOfKey(KeyBytes, StrongNameBytes));
  222. IFW32FALSE_EXIT(::SxspHashBytesToString(StrongNameBytes.GetArrayPtr(), StrongNameBytes.GetSize(), sbStrongName));
  223. bSuccess = TRUE;
  224. Exit:
  225. return bSuccess;
  226. }
  227. BOOL
  228. SxspAcquireStrongNameFromCertContext(
  229. CBaseStringBuffer &rbuffStrongNameString,
  230. CBaseStringBuffer &sbPublicKeyString,
  231. PCCERT_CONTEXT pCertContext
  232. )
  233. /*++
  234. Note to posterity:
  235. This is the other "black magic" of the strong-name stuff. Fusion URT takes whatever
  236. CryptExportKey blops out, tacks on a magic header of their design (which I have
  237. copied into SXS_PUBLIC_KEY_INFO), then hashes the whole thing. This routine knows
  238. how to interact with a pCertContext object (like one you'd get from a certificate
  239. file or by walking through a catalog) and turn the certificate into a strong name
  240. and public key blob. The public key blob is returned in a hex string, and can
  241. be converted back to bytes (for whatever purpose) via SxspHashStringToBytes.
  242. Don't change anything you see below, unless there's a bug or there's been a spec
  243. change. If you've got problems with this file, please notify Jon Wiswall (jonwis)
  244. and he'll be able to better help you with debugging or whatnot.
  245. --*/
  246. {
  247. BOOL bSuccess = FALSE;
  248. HCRYPTPROV hCryptProv = NULL;
  249. HCRYPTHASH hCryptHash = NULL;
  250. HCRYPTKEY hCryptKey = NULL;
  251. const SIZE_T KeyInfoBufferSize = 2048;
  252. CFusionArray<BYTE> bKeyInfo;
  253. PSXS_PUBLIC_KEY_INFO pKeyWrapping = NULL;
  254. DWORD dwDump = 0;
  255. CFusionArray<BYTE> bPublicKeyContainer;
  256. CFusionArray<BYTE> bStrongNameContainer;
  257. FN_TRACE_WIN32(bSuccess);
  258. PARAMETER_CHECK(pCertContext != NULL);
  259. PARAMETER_CHECK(pCertContext->pCertInfo != NULL);
  260. // NTRAID#NTBUG9 - 623698 - 2002/05/15 - jonwis - This is broken, use a growable buffer here
  261. // rather than a stack blob. This isn't future proof when people start using 16384-bit
  262. // keys.
  263. IFW32FALSE_EXIT(bKeyInfo.Win32SetSize(KeyInfoBufferSize));
  264. pKeyWrapping = reinterpret_cast<PSXS_PUBLIC_KEY_INFO>(bKeyInfo.GetArrayPtr());
  265. rbuffStrongNameString.Clear();
  266. sbPublicKeyString.Clear();
  267. //
  268. // Get a crypto context that only does RSA verification - ie, doesn't use private keys
  269. //
  270. IFW32FALSE_EXIT(::SxspAcquireGlobalCryptContext(&hCryptProv));
  271. //
  272. // Take the public key info that we found on this certificate context and blop it back
  273. // into a real internal crypto key.
  274. //
  275. IFW32FALSE_ORIGINATE_AND_EXIT(
  276. ::CryptImportPublicKeyInfoEx(
  277. hCryptProv,
  278. X509_ASN_ENCODING | PKCS_7_ASN_ENCODING,
  279. &(pCertContext->pCertInfo->SubjectPublicKeyInfo),
  280. CALG_RSA_SIGN,
  281. 0,
  282. NULL,
  283. &hCryptKey));
  284. //
  285. // The stuff we swizzle will be about 200 bytes, so this is serious overkill
  286. // until such time as people start using 16384-bit keys.
  287. //
  288. pKeyWrapping->KeyLength =
  289. KeyInfoBufferSize - offsetof(SXS_PUBLIC_KEY_INFO, pbKeyInfo);
  290. //
  291. // Extract the key data from the crypto key back into a byte stream. This seems to
  292. // be what the fusion-urt people do, in order to get a byte string to hash.
  293. //
  294. IFW32FALSE_ORIGINATE_AND_EXIT(
  295. CryptExportKey(
  296. hCryptKey,
  297. NULL,
  298. PUBLICKEYBLOB,
  299. 0,
  300. pKeyWrapping->pbKeyInfo,
  301. &pKeyWrapping->KeyLength));
  302. //
  303. // Sacred values from the fusion-urt people
  304. //
  305. pKeyWrapping->SigAlgID = CALG_RSA_SIGN;
  306. pKeyWrapping->HashAlgID = CALG_SHA1;
  307. dwDump = pKeyWrapping->KeyLength + offsetof(SXS_PUBLIC_KEY_INFO, pbKeyInfo);
  308. IFW32FALSE_EXIT(
  309. ::SxspHashBytesToString(
  310. reinterpret_cast<const BYTE*>(pKeyWrapping),
  311. dwDump,
  312. sbPublicKeyString));
  313. IFW32FALSE_EXIT(bPublicKeyContainer.Win32Assign(dwDump, bKeyInfo.GetArrayPtr()));
  314. IFW32FALSE_EXIT(
  315. ::SxspGetStrongNameOfKey(
  316. bPublicKeyContainer,
  317. bStrongNameContainer));
  318. INTERNAL_ERROR_CHECK(bStrongNameContainer.GetSize() == STRONG_NAME_BYTE_LENGTH);
  319. //
  320. // Great - this is the official strong name of the 2000 Fusolympics.
  321. //
  322. IFW32FALSE_EXIT(
  323. ::SxspHashBytesToString(
  324. bStrongNameContainer.GetArrayPtr(),
  325. STRONG_NAME_BYTE_LENGTH,
  326. rbuffStrongNameString));
  327. bSuccess = TRUE;
  328. Exit:
  329. if (hCryptKey != NULL) CryptDestroyKey(hCryptKey);
  330. if (hCryptHash != NULL) CryptDestroyHash(hCryptHash);
  331. return bSuccess;
  332. }
  333. inline BOOL
  334. SxspAreStrongNamesAllowedToNotMatchCatalogs(BOOL &bAllowed)
  335. {
  336. //
  337. // This function is our back-door past the strong-name system while
  338. // Whistler is still in beta/rtm. The test certificate, if installed,
  339. // indicates that it's ok to let strong names not match catalogs.
  340. //
  341. // The certificate data here is from \nt\admin\ntsetup\syssetup\crypto.c in
  342. // SetupAddOrRemoveTestCertificate. Please ensure that this gets updated.
  343. //
  344. BOOL fSuccess = FALSE;
  345. FN_TRACE_WIN32(fSuccess);
  346. CRYPT_HASH_BLOB HashBlob;
  347. HCERTSTORE hSystemStore = NULL;
  348. PCCERT_CONTEXT pCertContext = NULL;
  349. BYTE bTestRootHashList[][20] = {
  350. {0x2B, 0xD6, 0x3D, 0x28, 0xD7, 0xBC, 0xD0, 0xE2, 0x51, 0x19, 0x5A, 0xEB, 0x51, 0x92, 0x43, 0xC1, 0x31, 0x42, 0xEB, 0xC3}
  351. };
  352. bAllowed = FALSE;
  353. //
  354. // Cause the root store to be opened on the local machine.
  355. //
  356. IFW32NULL_ORIGINATE_AND_EXIT(
  357. hSystemStore = ::CertOpenStore(
  358. CERT_STORE_PROV_SYSTEM,
  359. 0,
  360. (HCRYPTPROV)NULL,
  361. CERT_SYSTEM_STORE_LOCAL_MACHINE,
  362. L"ROOT"));
  363. for (int i = 0; i < NUMBER_OF(bTestRootHashList); i++)
  364. {
  365. bool fNotFound;
  366. HashBlob.cbData = sizeof(bTestRootHashList[i]);
  367. HashBlob.pbData = bTestRootHashList[i];
  368. IFW32NULL_ORIGINATE_AND_EXIT_UNLESS2(
  369. pCertContext = ::CertFindCertificateInStore(
  370. hSystemStore,
  371. X509_ASN_ENCODING | PKCS_7_ASN_ENCODING,
  372. 0,
  373. CERT_FIND_HASH,
  374. &HashBlob,
  375. NULL),
  376. LIST_1(static_cast<DWORD>(CRYPT_E_NOT_FOUND)),
  377. fNotFound);
  378. if (pCertContext != NULL)
  379. {
  380. bAllowed = TRUE;
  381. break;
  382. }
  383. }
  384. if (!bAllowed)
  385. {
  386. ::FusionpDbgPrintEx(
  387. FUSION_DBG_LEVEL_INFO | FUSION_DBG_LEVEL_INSTALLATION,
  388. "SXS: %s - no test certificate installed on machine\n",
  389. __FUNCTION__);
  390. }
  391. fSuccess = TRUE;
  392. Exit:
  393. CSxsPreserveLastError ple;
  394. if (pCertContext) ::CertFreeCertificateContext(pCertContext);
  395. if (hSystemStore) ::CertCloseStore(hSystemStore, CERT_CLOSE_STORE_FORCE_FLAG);
  396. ple.Restore();
  397. return fSuccess;
  398. }
  399. CPublicKeyInformation::CPublicKeyInformation()
  400. : m_fInitialized(false)
  401. {
  402. }
  403. CPublicKeyInformation::~CPublicKeyInformation()
  404. {
  405. }
  406. BOOL
  407. CPublicKeyInformation::GetStrongNameBytes(
  408. OUT CFusionArray<BYTE> & cbStrongNameBytes
  409. ) const
  410. {
  411. FN_PROLOG_WIN32
  412. INTERNAL_ERROR_CHECK(m_fInitialized);
  413. IFW32FALSE_EXIT(m_StrongNameBytes.Win32Clone(cbStrongNameBytes));
  414. FN_EPILOG
  415. }
  416. BOOL
  417. CPublicKeyInformation::GetStrongNameString(
  418. OUT CBaseStringBuffer &rbuffStrongNameString
  419. ) const
  420. {
  421. FN_PROLOG_WIN32
  422. rbuffStrongNameString.Clear();
  423. INTERNAL_ERROR_CHECK(m_fInitialized);
  424. IFW32FALSE_EXIT(rbuffStrongNameString.Win32Assign(m_StrongNameString));
  425. FN_EPILOG
  426. }
  427. BOOL
  428. CPublicKeyInformation::GetPublicKeyBitLength(
  429. OUT ULONG &ulKeyLength
  430. ) const
  431. {
  432. BOOL fSuccess = FALSE;
  433. BOOL fLieAboutPublicKeyBitLength = FALSE;
  434. FN_TRACE_WIN32(fSuccess);
  435. ulKeyLength = 0;
  436. INTERNAL_ERROR_CHECK(m_fInitialized);
  437. IFW32FALSE_EXIT(::SxspAreStrongNamesAllowedToNotMatchCatalogs(fLieAboutPublicKeyBitLength));
  438. if (fLieAboutPublicKeyBitLength)
  439. {
  440. #if DBG
  441. FusionpDbgPrintEx(
  442. FUSION_DBG_LEVEL_WFP | FUSION_DBG_LEVEL_INFO,
  443. "SXS: %s() - Lying about key length because we're still in test mode (%lu actual, %lu spoofed.)\n",
  444. __FUNCTION__,
  445. m_KeyLength,
  446. SXS_MINIMAL_SIGNING_KEY_LENGTH);
  447. #endif
  448. ulKeyLength = SXS_MINIMAL_SIGNING_KEY_LENGTH;
  449. }
  450. else
  451. {
  452. ulKeyLength = m_KeyLength;
  453. }
  454. fSuccess = TRUE;
  455. Exit:
  456. return fSuccess;
  457. }
  458. BOOL
  459. CPublicKeyInformation::GetWrappedPublicKeyBytes(
  460. OUT CFusionArray<BYTE> &bPublicKeybytes
  461. ) const
  462. {
  463. FN_PROLOG_WIN32
  464. INTERNAL_ERROR_CHECK(m_fInitialized);
  465. IFW32FALSE_EXIT(m_PublicKeyBytes.Win32Clone(bPublicKeybytes));
  466. FN_EPILOG
  467. }
  468. BOOL
  469. CPublicKeyInformation::Initialize(
  470. IN const CBaseStringBuffer &rsbCatalogFile
  471. )
  472. {
  473. BOOL fSuccess = FALSE;
  474. CFusionFile CatalogFile;
  475. FN_TRACE_WIN32(fSuccess);
  476. IFW32FALSE_EXIT(m_CatalogSourceFileName.Win32Assign(rsbCatalogFile));
  477. IFW32FALSE_EXIT(
  478. CatalogFile.Win32CreateFile(
  479. rsbCatalogFile,
  480. GENERIC_READ,
  481. FILE_SHARE_READ,
  482. OPEN_EXISTING));
  483. IFW32FALSE_EXIT(this->Initialize(CatalogFile));
  484. fSuccess = TRUE;
  485. Exit:
  486. return fSuccess;
  487. }
  488. BOOL
  489. CPublicKeyInformation::Initialize(
  490. IN PCWSTR pszCatalogFile
  491. )
  492. {
  493. BOOL fSuccess = FALSE;
  494. CFusionFile CatalogFile;
  495. FN_TRACE_WIN32(fSuccess);
  496. IFW32FALSE_EXIT(m_CatalogSourceFileName.Win32Assign(pszCatalogFile, wcslen(pszCatalogFile)));
  497. IFW32FALSE_EXIT(
  498. CatalogFile.Win32CreateFile(
  499. pszCatalogFile,
  500. GENERIC_READ,
  501. FILE_SHARE_READ,
  502. OPEN_EXISTING));
  503. IFW32FALSE_EXIT(this->Initialize(CatalogFile));
  504. fSuccess = TRUE;
  505. Exit:
  506. return fSuccess;
  507. }
  508. BOOL
  509. CPublicKeyInformation::Initialize(
  510. IN CFusionFile& CatalogFileHandle
  511. )
  512. {
  513. BOOL fSuccess = FALSE;
  514. CFileMapping FileMapping;
  515. CMappedViewOfFile MappedFileView;
  516. ULONGLONG cbCatalogFile = 0;
  517. HCERTSTORE hTempStore = NULL;
  518. PCCERT_CONTEXT pSignerContext = NULL;
  519. PCCTL_CONTEXT pContext = NULL;
  520. FN_TRACE_WIN32(fSuccess);
  521. PARAMETER_CHECK(CatalogFileHandle != INVALID_HANDLE_VALUE);
  522. IFW32FALSE_EXIT(CatalogFileHandle.Win32GetSize(cbCatalogFile));
  523. IFW32FALSE_EXIT(FileMapping.Win32CreateFileMapping(CatalogFileHandle, PAGE_READONLY, cbCatalogFile, NULL));
  524. IFW32FALSE_EXIT(MappedFileView.Win32MapViewOfFile(FileMapping, FILE_MAP_READ, 0, (SIZE_T)cbCatalogFile));
  525. IFW32NULL_EXIT(pContext = (PCCTL_CONTEXT)CertCreateCTLContext(
  526. X509_ASN_ENCODING | PKCS_7_ASN_ENCODING,
  527. static_cast<const BYTE*>(static_cast<void*>(MappedFileView)),
  528. static_cast<DWORD>(cbCatalogFile)));
  529. hTempStore = pContext->hCertStore;
  530. IFW32FALSE_ORIGINATE_AND_EXIT(::CryptMsgGetAndVerifySigner(
  531. pContext->hCryptMsg,
  532. 1,
  533. &hTempStore,
  534. 0,
  535. &pSignerContext,
  536. NULL));
  537. // BUGBUG
  538. IFW32NULL_EXIT(pSignerContext);
  539. IFW32FALSE_EXIT(this->Initialize(pSignerContext));
  540. fSuccess = TRUE;
  541. Exit:
  542. return fSuccess;
  543. }
  544. BOOL
  545. CPublicKeyInformation::Initialize(IN PCCERT_CONTEXT pCertContext)
  546. {
  547. BOOL fSuccess = FALSE;
  548. DWORD dwNameStringLength;
  549. CStringBufferAccessor Access;
  550. FN_TRACE_WIN32(fSuccess);
  551. PARAMETER_CHECK(pCertContext != NULL);
  552. IFW32FALSE_EXIT(
  553. ::SxspAcquireStrongNameFromCertContext(
  554. m_StrongNameString,
  555. m_PublicKeyByteString,
  556. pCertContext));
  557. IFW32FALSE_EXIT(::SxspHashStringToBytes(m_StrongNameString, m_StrongNameString.Cch(), m_StrongNameBytes));
  558. IFW32FALSE_EXIT(::SxspHashStringToBytes(m_PublicKeyByteString, m_PublicKeyByteString.Cch(), m_PublicKeyBytes));
  559. IFW32ZERO_EXIT(m_KeyLength = CertGetPublicKeyLength(
  560. X509_ASN_ENCODING | PKCS_7_ASN_ENCODING,
  561. &pCertContext->pCertInfo->SubjectPublicKeyInfo));
  562. Access.Attach(&m_SignerDisplayName);
  563. dwNameStringLength = ::CertGetNameStringW(
  564. pCertContext,
  565. CERT_NAME_FRIENDLY_DISPLAY_TYPE,
  566. 0,
  567. NULL,
  568. Access.GetBufferPtr(),
  569. static_cast<DWORD>(Access.GetBufferCch()));
  570. if (dwNameStringLength == 0)
  571. {
  572. TRACE_WIN32_FAILURE_ORIGINATION(CertGetNameString);
  573. goto Exit;
  574. }
  575. if (dwNameStringLength > Access.GetBufferCch())
  576. {
  577. Access.Detach();
  578. IFW32FALSE_EXIT(m_SignerDisplayName.Win32ResizeBuffer(dwNameStringLength, eDoNotPreserveBufferContents));
  579. Access.Attach(&m_SignerDisplayName);
  580. dwNameStringLength = ::CertGetNameStringW(
  581. pCertContext,
  582. CERT_NAME_FRIENDLY_DISPLAY_TYPE,
  583. 0,
  584. NULL,
  585. Access.GetBufferPtr(),
  586. static_cast<DWORD>(Access.GetBufferCch()));
  587. }
  588. Access.Detach();
  589. m_fInitialized = true;
  590. fSuccess = TRUE;
  591. Exit:
  592. {
  593. CSxsPreserveLastError ple;
  594. if (pCertContext != NULL)
  595. ::CertFreeCertificateContext(pCertContext);
  596. ple.Restore();
  597. }
  598. return fSuccess;
  599. }
  600. BOOL
  601. CPublicKeyInformation::GetSignerNiceName(
  602. OUT CBaseStringBuffer &rbuffName
  603. )
  604. {
  605. FN_PROLOG_WIN32
  606. INTERNAL_ERROR_CHECK(m_fInitialized);
  607. IFW32FALSE_EXIT(rbuffName.Win32Assign(m_SignerDisplayName));
  608. FN_EPILOG
  609. }
  610. BOOL
  611. CPublicKeyInformation::DoesStrongNameMatchSigner(
  612. IN const CBaseStringBuffer &rbuffTestStrongName,
  613. OUT BOOL &rfStrongNameMatchesSigner
  614. ) const
  615. {
  616. BOOL fSuccess = FALSE;
  617. BOOL fCanStrongNameMismatch = FALSE;
  618. FN_TRACE_WIN32(fSuccess);
  619. rfStrongNameMatchesSigner = (::FusionpCompareStrings(
  620. rbuffTestStrongName,
  621. rbuffTestStrongName.Cch(),
  622. m_StrongNameString,
  623. m_StrongNameString.Cch(),
  624. false) == 0);
  625. if (!rfStrongNameMatchesSigner)
  626. {
  627. IFW32FALSE_EXIT(::SxspAreStrongNamesAllowedToNotMatchCatalogs(fCanStrongNameMismatch));
  628. if (fCanStrongNameMismatch)
  629. {
  630. ::FusionpDbgPrintEx(
  631. FUSION_DBG_LEVEL_WFP,
  632. "SXS.DLL: %s - !!notice!! Strong name %ls not in catalog %ls, test code allows this\n"
  633. " Please make sure that you have tested with realsigned catalogs.\n",
  634. __FUNCTION__,
  635. static_cast<PCWSTR>(rbuffTestStrongName),
  636. static_cast<PCWSTR>(m_CatalogSourceFileName));
  637. rfStrongNameMatchesSigner = TRUE;
  638. }
  639. }
  640. FN_EPILOG
  641. }