Source code of Windows XP (NT5)
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.

786 lines
20 KiB

  1. /*++
  2. Copyright (c) 2000 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. 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. //
  139. // Convert our pointer back for a second - it's a persisted version of this
  140. // structure anyhow.
  141. //
  142. pPubKeyInfo = (PSXS_PUBLIC_KEY_INFO)PublicKeyBits.GetArrayPtr();
  143. //
  144. // Make ourselves a hash object.
  145. //
  146. IFW32FALSE_EXIT(hHash.Win32Initialize(CALG_SHA1));
  147. //
  148. // Hash the actual data that we were passed in to generate the strong name.
  149. //
  150. IFW32FALSE_EXIT(
  151. hHash.Win32HashData(
  152. PublicKeyBits.GetArrayPtr(),
  153. PublicKeyBits.GetSize()));
  154. //
  155. // Find out how big the hash data really is from what was hashed.
  156. //
  157. IFW32FALSE_EXIT(hHash.Win32GetValue(StrongNameBits));
  158. //
  159. // Move the last eight bytes of the hash downwards using memmove, because
  160. // it knows about things like overlapping blocks.
  161. //
  162. PBYTE pbBits = static_cast<PBYTE>(StrongNameBits.GetArrayPtr());
  163. ::RtlMoveMemory(
  164. pbBits,
  165. pbBits + (StrongNameBits.GetSize() - STRONG_NAME_BYTE_LENGTH),
  166. STRONG_NAME_BYTE_LENGTH);
  167. pReverseByteString(pbBits, STRONG_NAME_BYTE_LENGTH);
  168. IFW32FALSE_EXIT(StrongNameBits.Win32SetSize(STRONG_NAME_BYTE_LENGTH, CFusionArray<BYTE>::eSetSizeModeExact));
  169. FN_EPILOG
  170. }
  171. BOOL
  172. SxspDoesStrongNameMatchKey(
  173. IN const CBaseStringBuffer &rbuffKeyString,
  174. IN const CBaseStringBuffer &rbuffStrongNameString,
  175. OUT BOOL &rfKeyMatchesStrongName
  176. )
  177. {
  178. FN_PROLOG_WIN32
  179. CSmallStringBuffer buffStrongNameCandidate;
  180. PARAMETER_CHECK(::SxspIsFullHexString(rbuffKeyString, rbuffKeyString.Cch()));
  181. PARAMETER_CHECK(::SxspIsFullHexString(rbuffStrongNameString, rbuffStrongNameString.Cch()));
  182. //
  183. // Convert the key over to its corresponding strong name
  184. //
  185. IFW32FALSE_EXIT(::SxspGetStrongNameOfKey(rbuffKeyString, buffStrongNameCandidate));
  186. //
  187. // And compare what the caller thinks it should be.
  188. //
  189. rfKeyMatchesStrongName = (::FusionpCompareStrings(
  190. rbuffStrongNameString,
  191. rbuffStrongNameString.Cch(),
  192. buffStrongNameCandidate,
  193. buffStrongNameCandidate.Cch(),
  194. false) == 0);
  195. FN_EPILOG
  196. }
  197. BOOL
  198. SxspGetStrongNameOfKey(
  199. IN const CBaseStringBuffer &rbuffKeyString,
  200. OUT CBaseStringBuffer &sbStrongName
  201. )
  202. {
  203. CFusionArray<BYTE> KeyBytes, StrongNameBytes;
  204. BOOL bSuccess = FALSE;
  205. FN_TRACE_WIN32(bSuccess);
  206. //
  207. // Convert the string to bytes, generate the strong name, convert back to
  208. // a string.
  209. //
  210. IFW32FALSE_EXIT(::SxspHashStringToBytes(rbuffKeyString, rbuffKeyString.Cch(), KeyBytes));
  211. IFW32FALSE_EXIT(::SxspGetStrongNameOfKey(KeyBytes, StrongNameBytes));
  212. IFW32FALSE_EXIT(::SxspHashBytesToString(StrongNameBytes.GetArrayPtr(), StrongNameBytes.GetSize(), sbStrongName));
  213. bSuccess = TRUE;
  214. Exit:
  215. return bSuccess;
  216. }
  217. BOOL
  218. SxspAcquireStrongNameFromCertContext(
  219. CBaseStringBuffer &rbuffStrongNameString,
  220. CBaseStringBuffer &sbPublicKeyString,
  221. PCCERT_CONTEXT pCertContext
  222. )
  223. /*++
  224. Note to posterity:
  225. This is the other "black magic" of the strong-name stuff. Fusion URT takes whatever
  226. CryptExportKey blops out, tacks on a magic header of their design (which I have
  227. copied into SXS_PUBLIC_KEY_INFO), then hashes the whole thing. This routine knows
  228. how to interact with a pCertContext object (like one you'd get from a certificate
  229. file or by walking through a catalog) and turn the certificate into a strong name
  230. and public key blob. The public key blob is returned in a hex string, and can
  231. be converted back to bytes (for whatever purpose) via SxspHashStringToBytes.
  232. Don't change anything you see below, unless there's a bug or there's been a spec
  233. change. If you've got problems with this file, please notify Jon Wiswall (jonwis)
  234. and he'll be able to better help you with debugging or whatnot.
  235. --*/
  236. {
  237. BOOL bSuccess = FALSE;
  238. HCRYPTPROV hCryptProv = NULL;
  239. HCRYPTHASH hCryptHash = NULL;
  240. HCRYPTKEY hCryptKey = NULL;
  241. BYTE bKeyInfo[2048] = { 0 };
  242. PSXS_PUBLIC_KEY_INFO pKeyWrapping = reinterpret_cast<PSXS_PUBLIC_KEY_INFO>(bKeyInfo);
  243. DWORD dwDump;
  244. CFusionArray<BYTE> bPublicKeyContainer;
  245. CFusionArray<BYTE> bStrongNameContainer;
  246. FN_TRACE_WIN32(bSuccess);
  247. rbuffStrongNameString.Clear();
  248. sbPublicKeyString.Clear();
  249. //
  250. // Get a crypto context that only does RSA verification - ie, doesn't use private keys
  251. //
  252. IFW32FALSE_EXIT(::SxspAcquireGlobalCryptContext(&hCryptProv));
  253. //
  254. // Take the public key info that we found on this certificate context and blop it back
  255. // into a real internal crypto key.
  256. //
  257. IFW32FALSE_ORIGINATE_AND_EXIT(
  258. ::CryptImportPublicKeyInfoEx(
  259. hCryptProv,
  260. X509_ASN_ENCODING | PKCS_7_ASN_ENCODING,
  261. &(pCertContext->pCertInfo->SubjectPublicKeyInfo),
  262. CALG_RSA_SIGN,
  263. 0,
  264. NULL,
  265. &hCryptKey));
  266. //
  267. // The stuff we swizzle will be about 200 bytes, so this is serious overkill
  268. // until such time as people start using 16384-bit keys.
  269. //
  270. pKeyWrapping->KeyLength =
  271. sizeof(bKeyInfo) - offsetof(SXS_PUBLIC_KEY_INFO, pbKeyInfo);
  272. //
  273. // Extract the key data from the crypto key back into a byte stream. This seems to
  274. // be what the fusion-urt people do, in order to get a byte string to hash.
  275. //
  276. IFW32FALSE_ORIGINATE_AND_EXIT(
  277. CryptExportKey(
  278. hCryptKey,
  279. NULL,
  280. PUBLICKEYBLOB,
  281. 0,
  282. pKeyWrapping->pbKeyInfo,
  283. &pKeyWrapping->KeyLength));
  284. //
  285. // Sacred values from the fusion-urt people
  286. //
  287. pKeyWrapping->SigAlgID = CALG_RSA_SIGN;
  288. pKeyWrapping->HashAlgID = CALG_SHA1;
  289. dwDump = pKeyWrapping->KeyLength + offsetof(SXS_PUBLIC_KEY_INFO, pbKeyInfo);
  290. IFW32FALSE_EXIT(
  291. ::SxspHashBytesToString(
  292. reinterpret_cast<const BYTE*>(pKeyWrapping),
  293. dwDump,
  294. sbPublicKeyString));
  295. IFW32FALSE_EXIT(bPublicKeyContainer.Win32Assign(dwDump, bKeyInfo));
  296. IFW32FALSE_EXIT(
  297. ::SxspGetStrongNameOfKey(
  298. bPublicKeyContainer,
  299. bStrongNameContainer));
  300. INTERNAL_ERROR_CHECK(bStrongNameContainer.GetSize() == STRONG_NAME_BYTE_LENGTH);
  301. //
  302. // Great - this is the official strong name of the 2000 Fusolympics.
  303. //
  304. IFW32FALSE_EXIT(
  305. ::SxspHashBytesToString(
  306. bStrongNameContainer.GetArrayPtr(),
  307. STRONG_NAME_BYTE_LENGTH,
  308. rbuffStrongNameString));
  309. bSuccess = TRUE;
  310. Exit:
  311. if (hCryptKey != NULL) CryptDestroyKey(hCryptKey);
  312. if (hCryptHash != NULL) CryptDestroyHash(hCryptHash);
  313. return bSuccess;
  314. }
  315. inline BOOL
  316. SxspAreStrongNamesAllowedToNotMatchCatalogs(BOOL &bAllowed)
  317. {
  318. //
  319. // This function is our back-door past the strong-name system while
  320. // Whistler is still in beta/rtm. The test certificate, if installed,
  321. // indicates that it's ok to let strong names not match catalogs.
  322. //
  323. // The certificate data here is from \nt\admin\ntsetup\syssetup\crypto.c in
  324. // SetupAddOrRemoveTestCertificate. Please ensure that this gets updated.
  325. //
  326. BOOL fSuccess = FALSE;
  327. FN_TRACE_WIN32(fSuccess);
  328. CRYPT_HASH_BLOB HashBlob;
  329. HCERTSTORE hSystemStore = NULL;
  330. PCCERT_CONTEXT pCertContext = NULL;
  331. BYTE bTestRootHashList[][20] = {
  332. {0x2B, 0xD6, 0x3D, 0x28, 0xD7, 0xBC, 0xD0, 0xE2, 0x51, 0x19, 0x5A, 0xEB, 0x51, 0x92, 0x43, 0xC1, 0x31, 0x42, 0xEB, 0xC3}
  333. };
  334. bAllowed = FALSE;
  335. //
  336. // Cause the root store to be opened on the local machine.
  337. //
  338. IFW32NULL_ORIGINATE_AND_EXIT(
  339. hSystemStore = ::CertOpenStore(
  340. CERT_STORE_PROV_SYSTEM,
  341. X509_ASN_ENCODING,
  342. (HCRYPTPROV)NULL,
  343. CERT_SYSTEM_STORE_LOCAL_MACHINE,
  344. L"ROOT"));
  345. for (int i = 0; i < NUMBER_OF(bTestRootHashList); i++)
  346. {
  347. bool fNotFound;
  348. HashBlob.cbData = sizeof(bTestRootHashList[i]);
  349. HashBlob.pbData = bTestRootHashList[i];
  350. IFW32NULL_ORIGINATE_AND_EXIT_UNLESS2(
  351. pCertContext = ::CertFindCertificateInStore(
  352. hSystemStore,
  353. X509_ASN_ENCODING,
  354. 0,
  355. CERT_FIND_HASH,
  356. &HashBlob,
  357. NULL),
  358. LIST_1(static_cast<DWORD>(CRYPT_E_NOT_FOUND)),
  359. fNotFound);
  360. if (pCertContext != NULL)
  361. {
  362. bAllowed = TRUE;
  363. break;
  364. }
  365. }
  366. if (!bAllowed)
  367. {
  368. ::FusionpDbgPrintEx(
  369. FUSION_DBG_LEVEL_INFO | FUSION_DBG_LEVEL_INSTALLATION,
  370. "SXS: %s - no test certificate installed on machine\n",
  371. __FUNCTION__);
  372. }
  373. fSuccess = TRUE;
  374. Exit:
  375. CSxsPreserveLastError ple;
  376. if (pCertContext) ::CertFreeCertificateContext(pCertContext);
  377. if (hSystemStore) ::CertCloseStore(hSystemStore, CERT_CLOSE_STORE_FORCE_FLAG);
  378. ple.Restore();
  379. return fSuccess;
  380. }
  381. CPublicKeyInformation::CPublicKeyInformation()
  382. : m_fInitialized(false)
  383. {
  384. }
  385. CPublicKeyInformation::~CPublicKeyInformation()
  386. {
  387. }
  388. BOOL
  389. CPublicKeyInformation::GetStrongNameBytes(
  390. OUT CFusionArray<BYTE> & cbStrongNameBytes
  391. ) const
  392. {
  393. FN_PROLOG_WIN32
  394. INTERNAL_ERROR_CHECK(m_fInitialized);
  395. IFW32FALSE_EXIT(m_StrongNameBytes.Win32Clone(cbStrongNameBytes));
  396. FN_EPILOG
  397. }
  398. BOOL
  399. CPublicKeyInformation::GetStrongNameString(
  400. OUT CBaseStringBuffer &rbuffStrongNameString
  401. ) const
  402. {
  403. FN_PROLOG_WIN32
  404. rbuffStrongNameString.Clear();
  405. INTERNAL_ERROR_CHECK(m_fInitialized);
  406. IFW32FALSE_EXIT(rbuffStrongNameString.Win32Assign(m_StrongNameString));
  407. FN_EPILOG
  408. }
  409. BOOL
  410. CPublicKeyInformation::GetPublicKeyBitLength(
  411. OUT ULONG &ulKeyLength
  412. ) const
  413. {
  414. BOOL fSuccess = FALSE;
  415. BOOL fLieAboutPublicKeyBitLength = FALSE;
  416. FN_TRACE_WIN32(fSuccess);
  417. ulKeyLength = 0;
  418. INTERNAL_ERROR_CHECK(m_fInitialized);
  419. IFW32FALSE_EXIT(::SxspAreStrongNamesAllowedToNotMatchCatalogs(fLieAboutPublicKeyBitLength));
  420. if (fLieAboutPublicKeyBitLength)
  421. {
  422. #if DBG
  423. FusionpDbgPrintEx(
  424. FUSION_DBG_LEVEL_WFP | FUSION_DBG_LEVEL_INFO,
  425. "SXS: %s() - Lying about key length because we're still in test mode (%lu actual, %lu spoofed.)\n",
  426. __FUNCTION__,
  427. m_KeyLength,
  428. SXS_MINIMAL_SIGNING_KEY_LENGTH);
  429. #endif
  430. ulKeyLength = SXS_MINIMAL_SIGNING_KEY_LENGTH;
  431. }
  432. else
  433. {
  434. ulKeyLength = m_KeyLength;
  435. }
  436. fSuccess = TRUE;
  437. Exit:
  438. return fSuccess;
  439. }
  440. BOOL
  441. CPublicKeyInformation::GetWrappedPublicKeyBytes(
  442. OUT CFusionArray<BYTE> &bPublicKeybytes
  443. ) const
  444. {
  445. FN_PROLOG_WIN32
  446. INTERNAL_ERROR_CHECK(m_fInitialized);
  447. IFW32FALSE_EXIT(m_PublicKeyBytes.Win32Clone(bPublicKeybytes));
  448. FN_EPILOG
  449. }
  450. BOOL
  451. CPublicKeyInformation::Initialize(
  452. IN const CBaseStringBuffer &rsbCatalogFile
  453. )
  454. {
  455. BOOL fSuccess = FALSE;
  456. CFusionFile CatalogFile;
  457. FN_TRACE_WIN32(fSuccess);
  458. IFW32FALSE_EXIT(m_CatalogSourceFileName.Win32Assign(rsbCatalogFile));
  459. IFW32FALSE_EXIT(
  460. CatalogFile.Win32CreateFile(
  461. rsbCatalogFile,
  462. GENERIC_READ,
  463. FILE_SHARE_READ,
  464. OPEN_EXISTING));
  465. IFW32FALSE_EXIT(this->Initialize(CatalogFile));
  466. fSuccess = TRUE;
  467. Exit:
  468. return fSuccess;
  469. }
  470. BOOL
  471. CPublicKeyInformation::Initialize(
  472. IN PCWSTR pszCatalogFile
  473. )
  474. {
  475. BOOL fSuccess = FALSE;
  476. CFusionFile CatalogFile;
  477. FN_TRACE_WIN32(fSuccess);
  478. IFW32FALSE_EXIT(m_CatalogSourceFileName.Win32Assign(pszCatalogFile, wcslen(pszCatalogFile)));
  479. IFW32FALSE_EXIT(
  480. CatalogFile.Win32CreateFile(
  481. pszCatalogFile,
  482. GENERIC_READ,
  483. FILE_SHARE_READ,
  484. OPEN_EXISTING));
  485. IFW32FALSE_EXIT(this->Initialize(CatalogFile));
  486. fSuccess = TRUE;
  487. Exit:
  488. return fSuccess;
  489. }
  490. BOOL
  491. CPublicKeyInformation::Initialize(
  492. IN CFusionFile& CatalogFileHandle
  493. )
  494. {
  495. BOOL fSuccess = FALSE;
  496. CFileMapping FileMapping;
  497. CMappedViewOfFile MappedFileView;
  498. ULONGLONG cbCatalogFile = 0;
  499. HCERTSTORE hTempStore = NULL;
  500. PCCERT_CONTEXT pSignerContext = NULL;
  501. PCCTL_CONTEXT pContext = NULL;
  502. FN_TRACE_WIN32(fSuccess);
  503. PARAMETER_CHECK(CatalogFileHandle != INVALID_HANDLE_VALUE);
  504. IFW32FALSE_EXIT(CatalogFileHandle.Win32GetSize(cbCatalogFile));
  505. IFW32FALSE_EXIT(FileMapping.Win32CreateFileMapping(CatalogFileHandle, PAGE_READONLY, cbCatalogFile, NULL));
  506. IFW32FALSE_EXIT(MappedFileView.Win32MapViewOfFile(FileMapping, FILE_MAP_READ, 0, (SIZE_T)cbCatalogFile));
  507. IFW32NULL_EXIT(pContext = (PCCTL_CONTEXT)CertCreateCTLContext(
  508. X509_ASN_ENCODING | PKCS_7_ASN_ENCODING,
  509. static_cast<const BYTE*>(static_cast<void*>(MappedFileView)),
  510. static_cast<DWORD>(cbCatalogFile)));
  511. hTempStore = pContext->hCertStore;
  512. IFW32FALSE_ORIGINATE_AND_EXIT(::CryptMsgGetAndVerifySigner(
  513. pContext->hCryptMsg,
  514. 1,
  515. &hTempStore,
  516. 0,
  517. &pSignerContext,
  518. NULL));
  519. // BUGBUG
  520. IFW32NULL_EXIT(pSignerContext);
  521. IFW32FALSE_EXIT(this->Initialize(pSignerContext));
  522. fSuccess = TRUE;
  523. Exit:
  524. return fSuccess;
  525. }
  526. BOOL
  527. CPublicKeyInformation::Initialize(IN PCCERT_CONTEXT pCertContext)
  528. {
  529. BOOL fSuccess = FALSE;
  530. DWORD dwNameStringLength;
  531. CStringBufferAccessor Access;
  532. FN_TRACE_WIN32(fSuccess);
  533. PARAMETER_CHECK(pCertContext != NULL);
  534. IFW32FALSE_EXIT(
  535. ::SxspAcquireStrongNameFromCertContext(
  536. m_StrongNameString,
  537. m_PublicKeyByteString,
  538. pCertContext));
  539. IFW32FALSE_EXIT(SxspHashStringToBytes(m_StrongNameString, m_StrongNameString.Cch(), m_StrongNameBytes));
  540. IFW32FALSE_EXIT(SxspHashStringToBytes(m_PublicKeyByteString, m_PublicKeyByteString.Cch(), m_PublicKeyBytes));
  541. IFW32ZERO_EXIT(m_KeyLength = CertGetPublicKeyLength(
  542. X509_ASN_ENCODING | PKCS_7_ASN_ENCODING,
  543. &pCertContext->pCertInfo->SubjectPublicKeyInfo));
  544. Access.Attach(&m_SignerDisplayName);
  545. dwNameStringLength = ::CertGetNameStringW(
  546. pCertContext,
  547. CERT_NAME_FRIENDLY_DISPLAY_TYPE,
  548. 0,
  549. NULL,
  550. Access.GetBufferPtr(),
  551. static_cast<DWORD>(Access.GetBufferCch()));
  552. if (dwNameStringLength == 0)
  553. {
  554. TRACE_WIN32_FAILURE_ORIGINATION(CertGetNameString);
  555. goto Exit;
  556. }
  557. if (dwNameStringLength > Access.GetBufferCch())
  558. {
  559. Access.Detach();
  560. IFW32FALSE_EXIT(m_SignerDisplayName.Win32ResizeBuffer(dwNameStringLength, eDoNotPreserveBufferContents));
  561. Access.Attach(&m_SignerDisplayName);
  562. dwNameStringLength = ::CertGetNameStringW(
  563. pCertContext,
  564. CERT_NAME_FRIENDLY_DISPLAY_TYPE,
  565. 0,
  566. NULL,
  567. Access.GetBufferPtr(),
  568. static_cast<DWORD>(Access.GetBufferCch()));
  569. }
  570. Access.Detach();
  571. m_fInitialized = true;
  572. fSuccess = TRUE;
  573. Exit:
  574. {
  575. CSxsPreserveLastError ple;
  576. if (pCertContext != NULL)
  577. ::CertFreeCertificateContext(pCertContext);
  578. ple.Restore();
  579. }
  580. return fSuccess;
  581. }
  582. BOOL
  583. CPublicKeyInformation::GetSignerNiceName(
  584. OUT CBaseStringBuffer &rbuffName
  585. )
  586. {
  587. FN_PROLOG_WIN32
  588. INTERNAL_ERROR_CHECK(m_fInitialized);
  589. IFW32FALSE_EXIT(rbuffName.Win32Assign(m_SignerDisplayName));
  590. FN_EPILOG
  591. }
  592. BOOL
  593. CPublicKeyInformation::DoesStrongNameMatchSigner(
  594. IN const CBaseStringBuffer &rbuffTestStrongName,
  595. OUT BOOL &rfStrongNameMatchesSigner
  596. ) const
  597. {
  598. BOOL fSuccess = FALSE;
  599. BOOL fCanStrongNameMismatch = FALSE;
  600. FN_TRACE_WIN32(fSuccess);
  601. rfStrongNameMatchesSigner = (::FusionpCompareStrings(
  602. rbuffTestStrongName,
  603. rbuffTestStrongName.Cch(),
  604. m_StrongNameString,
  605. m_StrongNameString.Cch(),
  606. false) == 0);
  607. if (!rfStrongNameMatchesSigner)
  608. {
  609. IFW32FALSE_EXIT(::SxspAreStrongNamesAllowedToNotMatchCatalogs(fCanStrongNameMismatch));
  610. if (fCanStrongNameMismatch)
  611. {
  612. ::FusionpDbgPrintEx(
  613. FUSION_DBG_LEVEL_WFP,
  614. "SXS.DLL: %s - !!notice!! Strong name %ls not in catalog %ls, test code allows this\n"
  615. " Please make sure that you have tested with realsigned catalogs.\n",
  616. __FUNCTION__,
  617. static_cast<PCWSTR>(rbuffTestStrongName),
  618. static_cast<PCWSTR>(m_CatalogSourceFileName));
  619. rfStrongNameMatchesSigner = TRUE;
  620. }
  621. }
  622. FN_EPILOG
  623. }