aboutsummaryrefslogtreecommitdiff
path: root/src/engine/cache.cpp
diff options
context:
space:
mode:
authorBob Arnson <bob@firegiant.com>2021-01-31 19:28:47 -0500
committerBob Arnson <bob@firegiant.com>2021-01-31 19:35:27 -0500
commitf1f1a124df59e8639c2bcbfa7d3a4b37fb348bb7 (patch)
tree6866de4e995d3ae55affff6c70e3d93175583c65 /src/engine/cache.cpp
parent0e41fb8be9690ca7b81ec4df0734ead1978a9cf0 (diff)
downloadwix-f1f1a124df59e8639c2bcbfa7d3a4b37fb348bb7.tar.gz
wix-f1f1a124df59e8639c2bcbfa7d3a4b37fb348bb7.tar.bz2
wix-f1f1a124df59e8639c2bcbfa7d3a4b37fb348bb7.zip
Remove Burn Authenticode
Fixes https://github.com/wixtoolset/issues/issues/6301
Diffstat (limited to '')
-rw-r--r--src/engine/cache.cpp252
1 files changed, 5 insertions, 247 deletions
diff --git a/src/engine/cache.cpp b/src/engine/cache.cpp
index 315281bc..92a79eb9 100644
--- a/src/engine/cache.cpp
+++ b/src/engine/cache.cpp
@@ -94,15 +94,6 @@ static HRESULT VerifyHash(
94 __in_z LPCWSTR wzUnverifiedPayloadPath, 94 __in_z LPCWSTR wzUnverifiedPayloadPath,
95 __in HANDLE hFile 95 __in HANDLE hFile
96 ); 96 );
97static HRESULT VerifyPayloadWithCatalog(
98 __in BURN_PAYLOAD* pPayload,
99 __in_z LPCWSTR wzUnverifiedPayloadPath,
100 __in HANDLE hFile
101 );
102static HRESULT VerifyPayloadAgainstChain(
103 __in BURN_PAYLOAD* pPayload,
104 __in PCCERT_CHAIN_CONTEXT pChainContext
105 );
106 97
107 98
108extern "C" HRESULT CacheInitialize( 99extern "C" HRESULT CacheInitialize(
@@ -189,7 +180,7 @@ LExit:
189} 180}
190 181
191extern "C" HRESULT CacheEnsureWorkingFolder( 182extern "C" HRESULT CacheEnsureWorkingFolder(
192 __in_z LPCWSTR wzBundleId, 183 __in_z_opt LPCWSTR wzBundleId,
193 __deref_out_z_opt LPWSTR* psczWorkingFolder 184 __deref_out_z_opt LPWSTR* psczWorkingFolder
194 ) 185 )
195{ 186{
@@ -964,56 +955,6 @@ LExit:
964 return hr; 955 return hr;
965} 956}
966 957
967extern "C" HRESULT CacheVerifyPayloadSignature(
968 __in BURN_PAYLOAD* pPayload,
969 __in_z LPCWSTR wzUnverifiedPayloadPath,
970 __in HANDLE hFile
971 )
972{
973 HRESULT hr = S_OK;
974 LONG er = ERROR_SUCCESS;
975
976 GUID guidAuthenticode = WINTRUST_ACTION_GENERIC_VERIFY_V2;
977 WINTRUST_FILE_INFO wfi = { };
978 WINTRUST_DATA wtd = { };
979 CRYPT_PROVIDER_DATA* pProviderData = NULL;
980 CRYPT_PROVIDER_SGNR* pSigner = NULL;
981
982 // Verify the payload assuming online.
983 wfi.cbStruct = sizeof(wfi);
984 wfi.pcwszFilePath = wzUnverifiedPayloadPath;
985 wfi.hFile = hFile;
986
987 wtd.cbStruct = sizeof(wtd);
988 wtd.dwUnionChoice = WTD_CHOICE_FILE;
989 wtd.pFile = &wfi;
990 wtd.dwStateAction = WTD_STATEACTION_VERIFY;
991 wtd.dwProvFlags = WTD_REVOCATION_CHECK_CHAIN_EXCLUDE_ROOT;
992 wtd.dwUIChoice = WTD_UI_NONE;
993
994 er = ::WinVerifyTrust(static_cast<HWND>(INVALID_HANDLE_VALUE), &guidAuthenticode, &wtd);
995 if (er)
996 {
997 // Verify the payload assuming offline.
998 wtd.dwProvFlags |= WTD_CACHE_ONLY_URL_RETRIEVAL;
999
1000 er = ::WinVerifyTrust(static_cast<HWND>(INVALID_HANDLE_VALUE), &guidAuthenticode, &wtd);
1001 ExitOnWin32Error(er, hr, "Failed authenticode verification of payload: %ls", wzUnverifiedPayloadPath);
1002 }
1003
1004 pProviderData = WTHelperProvDataFromStateData(wtd.hWVTStateData);
1005 ExitOnNullWithLastError(pProviderData, hr, "Failed to get provider state from authenticode certificate.");
1006
1007 pSigner = WTHelperGetProvSignerFromChain(pProviderData, 0, FALSE, 0);
1008 ExitOnNullWithLastError(pSigner, hr, "Failed to get signer chain from authenticode certificate.");
1009
1010 hr = VerifyPayloadAgainstChain(pPayload, pSigner->pChainContext);
1011 ExitOnFailure(hr, "Failed to verify expected payload against actual certificate chain.");
1012
1013LExit:
1014 return hr;
1015}
1016
1017extern "C" void CacheCleanup( 958extern "C" void CacheCleanup(
1018 __in BOOL fPerMachine, 959 __in BOOL fPerMachine,
1019 __in_z LPCWSTR wzBundleId 960 __in_z LPCWSTR wzBundleId
@@ -1098,7 +1039,7 @@ extern "C" void CacheUninitialize()
1098// Internal functions. 1039// Internal functions.
1099 1040
1100static HRESULT CalculateWorkingFolder( 1041static HRESULT CalculateWorkingFolder(
1101 __in_z LPCWSTR /*wzBundleId*/, 1042 __in_z_opt LPCWSTR /*wzBundleId*/,
1102 __deref_out_z LPWSTR* psczWorkingFolder 1043 __deref_out_z LPWSTR* psczWorkingFolder
1103 ) 1044 )
1104{ 1045{
@@ -1387,18 +1328,7 @@ static HRESULT VerifyThenTransferPayload(
1387 ExitWithLastError(hr, "Failed to open payload in working path: %ls", wzUnverifiedPayloadPath); 1328 ExitWithLastError(hr, "Failed to open payload in working path: %ls", wzUnverifiedPayloadPath);
1388 } 1329 }
1389 1330
1390 // If the payload has a certificate root public key identifier provided, verify the certificate. 1331 if (pPayload->pbHash) // the payload should have a hash we can use to verify it.
1391 if (pPayload->pbCertificateRootPublicKeyIdentifier)
1392 {
1393 hr = CacheVerifyPayloadSignature(pPayload, wzUnverifiedPayloadPath, hFile);
1394 ExitOnFailure(hr, "Failed to verify payload signature: %ls", wzCachedPath);
1395 }
1396 else if (pPayload->pCatalog) // If catalog files are specified, attempt to verify the file with a catalog file
1397 {
1398 hr = VerifyPayloadWithCatalog(pPayload, wzUnverifiedPayloadPath, hFile);
1399 ExitOnFailure(hr, "Failed to verify payload signature: %ls", wzCachedPath);
1400 }
1401 else if (pPayload->pbHash) // the payload should have a hash we can use to verify it.
1402 { 1332 {
1403 hr = VerifyHash(pPayload->pbHash, pPayload->cbHash, wzUnverifiedPayloadPath, hFile); 1333 hr = VerifyHash(pPayload->pbHash, pPayload->cbHash, wzUnverifiedPayloadPath, hFile);
1404 ExitOnFailure(hr, "Failed to verify payload hash: %ls", wzCachedPath); 1334 ExitOnFailure(hr, "Failed to verify payload hash: %ls", wzCachedPath);
@@ -1466,18 +1396,7 @@ static HRESULT VerifyFileAgainstPayload(
1466 ExitOnRootFailure(hr, "Failed to open payload at path: %ls", wzVerifyPath); 1396 ExitOnRootFailure(hr, "Failed to open payload at path: %ls", wzVerifyPath);
1467 } 1397 }
1468 1398
1469 // If the payload has a certificate root public key identifier provided, verify the certificate. 1399 if (pPayload->pbHash) // the payload should have a hash we can use to verify it.
1470 if (pPayload->pbCertificateRootPublicKeyIdentifier)
1471 {
1472 hr = CacheVerifyPayloadSignature(pPayload, wzVerifyPath, hFile);
1473 ExitOnFailure(hr, "Failed to verify signature of payload: %ls", pPayload->sczKey);
1474 }
1475 else if (pPayload->pCatalog) // If catalog files are specified, attempt to verify the file with a catalog file
1476 {
1477 hr = VerifyPayloadWithCatalog(pPayload, wzVerifyPath, hFile);
1478 ExitOnFailure(hr, "Failed to verify catalog signature of payload: %ls", pPayload->sczKey);
1479 }
1480 else if (pPayload->pbHash) // the payload should have a hash we can use to verify it.
1481 { 1400 {
1482 hr = VerifyHash(pPayload->pbHash, pPayload->cbHash, wzVerifyPath, hFile); 1401 hr = VerifyHash(pPayload->pbHash, pPayload->cbHash, wzVerifyPath, hFile);
1483 ExitOnFailure(hr, "Failed to verify hash of payload: %ls", pPayload->sczKey); 1402 ExitOnFailure(hr, "Failed to verify hash of payload: %ls", pPayload->sczKey);
@@ -1517,7 +1436,7 @@ LExit:
1517 1436
1518static HRESULT ResetPathPermissions( 1437static HRESULT ResetPathPermissions(
1519 __in BOOL fPerMachine, 1438 __in BOOL fPerMachine,
1520 __in LPCWSTR wzPath 1439 __in_z LPCWSTR wzPath
1521 ) 1440 )
1522{ 1441{
1523 HRESULT hr = S_OK; 1442 HRESULT hr = S_OK;
@@ -1863,164 +1782,3 @@ LExit:
1863 1782
1864 return hr; 1783 return hr;
1865} 1784}
1866
1867static HRESULT VerifyPayloadWithCatalog(
1868 __in BURN_PAYLOAD* pPayload,
1869 __in_z LPCWSTR wzUnverifiedPayloadPath,
1870 __in HANDLE hFile
1871 )
1872{
1873 HRESULT hr = S_FALSE;
1874 DWORD er = ERROR_SUCCESS;
1875 WINTRUST_DATA WinTrustData = { };
1876 WINTRUST_CATALOG_INFO WinTrustCatalogInfo = { };
1877 GUID gSubSystemDriver = WINTRUST_ACTION_GENERIC_VERIFY_V2;
1878 LPWSTR sczLowerCaseFile = NULL;
1879 LPWSTR pCurrent = NULL;
1880 LPWSTR sczName = NULL;
1881 DWORD dwHashSize = 0;
1882 DWORD dwTagSize;
1883 LPBYTE pbHash = NULL;
1884
1885 // Get lower case file name. Older operating systems need a lower case file
1886 // to match in the catalog
1887 hr = StrAllocString(&sczLowerCaseFile, wzUnverifiedPayloadPath, 0);
1888 ExitOnFailure(hr, "Failed to allocate memory");
1889
1890 // Go through each character doing the lower case of each letter
1891 pCurrent = sczLowerCaseFile;
1892 while ('\0' != *pCurrent)
1893 {
1894 *pCurrent = (WCHAR)_tolower(*pCurrent);
1895 pCurrent++;
1896 }
1897
1898 // Get file hash
1899 CryptCATAdminCalcHashFromFileHandle(hFile, &dwHashSize, pbHash, 0);
1900 er = ::GetLastError();
1901 if (ERROR_INSUFFICIENT_BUFFER == er)
1902 {
1903 pbHash = (LPBYTE)MemAlloc(dwHashSize, TRUE);
1904 if (!CryptCATAdminCalcHashFromFileHandle(hFile, &dwHashSize, pbHash, 0))
1905 {
1906 ExitWithLastError(hr, "Failed to get file hash.");
1907 }
1908 }
1909 else
1910 {
1911 ExitOnWin32Error(er, hr, "Failed to get file hash.");
1912 }
1913
1914 // Make the hash into a string. This is the member tag for the catalog
1915 dwTagSize = (dwHashSize * 2) + 1;
1916 hr = StrAlloc(&sczName, dwTagSize);
1917 ExitOnFailure(hr, "Failed to allocate string.");
1918 hr = StrHexEncode(pbHash, dwHashSize, sczName, dwTagSize);
1919 ExitOnFailure(hr, "Failed to encode file hash.");
1920
1921 // Set up the WinVerifyTrust structures assuming online.
1922 WinTrustData.cbStruct = sizeof(WINTRUST_DATA);
1923 WinTrustData.dwUIChoice = WTD_UI_NONE;
1924 WinTrustData.dwUnionChoice = WTD_CHOICE_CATALOG;
1925 WinTrustData.dwStateAction = WTD_STATEACTION_VERIFY;
1926 WinTrustData.dwProvFlags = WTD_REVOCATION_CHECK_CHAIN_EXCLUDE_ROOT;
1927 WinTrustData.pCatalog = &WinTrustCatalogInfo;
1928
1929 WinTrustCatalogInfo.cbStruct = sizeof(WINTRUST_CATALOG_INFO);
1930 WinTrustCatalogInfo.pbCalculatedFileHash = pbHash;
1931 WinTrustCatalogInfo.cbCalculatedFileHash = dwHashSize;
1932 WinTrustCatalogInfo.hMemberFile = hFile;
1933 WinTrustCatalogInfo.pcwszMemberTag = sczName;
1934 WinTrustCatalogInfo.pcwszMemberFilePath = sczLowerCaseFile;
1935 WinTrustCatalogInfo.pcwszCatalogFilePath = pPayload->pCatalog->sczLocalFilePath;
1936
1937 hr = ::WinVerifyTrust(static_cast<HWND>(INVALID_HANDLE_VALUE), &gSubSystemDriver, &WinTrustData);
1938 if (hr)
1939 {
1940 // Set up the WinVerifyTrust structures assuming online.
1941 WinTrustData.dwProvFlags |= WTD_CACHE_ONLY_URL_RETRIEVAL;
1942
1943 er = ::WinVerifyTrust(static_cast<HWND>(INVALID_HANDLE_VALUE), &gSubSystemDriver, &WinTrustData);
1944
1945 // WinVerifyTrust returns 0 for success, a few different Win32 error codes if it can't
1946 // find the provider, and any other error code is provider specific, so may not
1947 // be an actual Win32 error code
1948 ExitOnWin32Error(er, hr, "Could not verify file %ls.", wzUnverifiedPayloadPath);
1949 }
1950
1951 // Need to close the WinVerifyTrust action
1952 WinTrustData.dwStateAction = WTD_STATEACTION_CLOSE;
1953 er = ::WinVerifyTrust(static_cast<HWND>(INVALID_HANDLE_VALUE), &gSubSystemDriver, &WinTrustData);
1954 ExitOnWin32Error(er, hr, "Could not close verify handle.");
1955
1956LExit:
1957 ReleaseStr(sczLowerCaseFile);
1958 ReleaseStr(sczName);
1959 ReleaseMem(pbHash);
1960
1961 return hr;
1962}
1963
1964static HRESULT VerifyPayloadAgainstChain(
1965 __in BURN_PAYLOAD* pPayload,
1966 __in PCCERT_CHAIN_CONTEXT pChainContext
1967 )
1968{
1969 HRESULT hr = S_OK;
1970 PCCERT_CONTEXT pChainElementCertContext = NULL;
1971
1972 BYTE rgbPublicKeyIdentifier[SHA1_HASH_LEN] = { };
1973 DWORD cbPublicKeyIdentifier = sizeof(rgbPublicKeyIdentifier);
1974 BYTE* pbThumbprint = NULL;
1975 DWORD cbThumbprint = 0;
1976
1977 // Walk up the chain looking for a certificate in the chain that matches our expected public key identifier
1978 // and thumbprint (if a thumbprint was provided).
1979 HRESULT hrChainVerification = E_NOTFOUND; // assume we won't find a match.
1980 for (DWORD i = 0; i < pChainContext->rgpChain[0]->cElement; ++i)
1981 {
1982 pChainElementCertContext = pChainContext->rgpChain[0]->rgpElement[i]->pCertContext;
1983
1984 // Get the certificate's public key identifier.
1985 if (!::CryptHashPublicKeyInfo(NULL, CALG_SHA1, 0, X509_ASN_ENCODING, &pChainElementCertContext->pCertInfo->SubjectPublicKeyInfo, rgbPublicKeyIdentifier, &cbPublicKeyIdentifier))
1986 {
1987 ExitWithLastError(hr, "Failed to get certificate public key identifier.");
1988 }
1989
1990 // Compare the certificate's public key identifier with the payload's public key identifier. If they
1991 // match, we're one step closer to the a positive result.
1992 if (pPayload->cbCertificateRootPublicKeyIdentifier == cbPublicKeyIdentifier &&
1993 0 == memcmp(pPayload->pbCertificateRootPublicKeyIdentifier, rgbPublicKeyIdentifier, cbPublicKeyIdentifier))
1994 {
1995 // If the payload specified a thumbprint for the certificate, verify it.
1996 if (pPayload->pbCertificateRootThumbprint)
1997 {
1998 hr = CertReadProperty(pChainElementCertContext, CERT_SHA1_HASH_PROP_ID, &pbThumbprint, &cbThumbprint);
1999 ExitOnFailure(hr, "Failed to read certificate thumbprint.");
2000
2001 if (pPayload->cbCertificateRootThumbprint == cbThumbprint &&
2002 0 == memcmp(pPayload->pbCertificateRootThumbprint, pbThumbprint, cbThumbprint))
2003 {
2004 // If we got here, we found that our payload public key identifier and thumbprint
2005 // matched an element in the certficate chain.
2006 hrChainVerification = S_OK;
2007 break;
2008 }
2009
2010 ReleaseNullMem(pbThumbprint);
2011 }
2012 else // no thumbprint match necessary so we're good to go.
2013 {
2014 hrChainVerification = S_OK;
2015 break;
2016 }
2017 }
2018 }
2019 hr = hrChainVerification;
2020 ExitOnFailure(hr, "Failed to find expected public key in certificate chain.");
2021
2022LExit:
2023 ReleaseMem(pbThumbprint);
2024
2025 return hr;
2026}