Windows: Fix MSI traveler disk creation with WHQL-signed drivers

Make MSI-installed VeraCrypt use the IDRIX-signed COMReg package as the
source for traveler files, matching the EXE installer flow. COMReg now
packages the x64 traveler payload, so traveler creation no longer has to
copy the installed x64 driver from appDir\veracrypt.sys and verify it
against a Microsoft WHQL certificate fingerprint.

Keep Microsoft WHQL certificate verification only for the loose portable
driver fallback, where driver files cannot be signed with the IDRIX code
signing certificate. The normal VerifyModuleSignature path now remains
IDRIX-only.

Also validate that an MSI COMReg package actually contains the required
x64 traveler files before reporting success, avoiding partial traveler
directories when the package payload is incomplete.
This commit is contained in:
Mounir IDRASSI
2026-04-14 18:43:07 +09:00
parent 250a488a84
commit 976bb3767b
4 changed files with 76 additions and 82 deletions

View File

@@ -21,8 +21,12 @@ int APIENTRY _tWinMain(HINSTANCE hInstance,
if (s)
s[1] = 0;
/* Create self-extracting package */
MakeSelfExtractingPackage (NULL, SetupFilesDir, TRUE);
/*
* Create a self-extracting package containing the traveler files.
* The MSI traveler creation path verifies this IDRIX-signed package
* instead of verifying individual WHQL-signed driver files.
*/
MakeSelfExtractingPackage (NULL, SetupFilesDir, FALSE);
}
return 0;

View File

@@ -314,15 +314,41 @@ static unsigned char gpbSha512CodeSignCertFingerprint[64] = {
0xF1, 0x08, 0xF3, 0xA8
};
static unsigned char gpbSha512MSCodeSignCertFingerprint[64] = {
0x17, 0x8C, 0x1B, 0x37, 0x70, 0xBF, 0x8B, 0xDF, 0x84, 0x55, 0xC5, 0x18,
0x13, 0x64, 0xE9, 0x65, 0x6D, 0x67, 0xCA, 0x0C, 0xD6, 0x3B, 0x9E, 0x7B,
0x9B, 0x6A, 0x63, 0xD6, 0x19, 0xAE, 0xD7, 0xBA, 0xBE, 0x5C, 0xCB, 0xD1,
0x07, 0x89, 0x07, 0xFB, 0x12, 0xC0, 0x2C, 0x94, 0x86, 0xEB, 0x67, 0x0B,
0x9C, 0x97, 0xEB, 0x20, 0x38, 0x13, 0x9C, 0x0F, 0x56, 0x93, 0x1B, 0x19,
0x6F, 0x8F, 0x6A, 0x39
/*
* SHA-512 hashes of the DER-encoded Authenticode leaf certificates used by
* Microsoft WHQL signing for the current VeraCrypt driver files. These are
* accepted only by VerifyModuleSignatureAllowingMicrosoftWHQL(), which is used
* for loose portable driver files that cannot be signed by the IDRIX
* certificate.
*/
static unsigned char gpbSha512MSWHQLCertFingerprints[][64] = {
/*
* SHA-1 thumbprint 3847B761C2846DB72F61149176D09F9BB2D43E8A,
* observed on the latest WHQL signing certificate.
*/
{
0x29, 0x85, 0xDC, 0xD4, 0x85, 0xBF, 0x3C, 0x48, 0xA6, 0x08, 0x13, 0x8E,
0x53, 0xE6, 0x7A, 0x98, 0x7F, 0xE8, 0x1D, 0x9C, 0xE8, 0x37, 0xDF, 0xE0,
0xCD, 0x68, 0xF9, 0x97, 0x11, 0x14, 0xF7, 0xEF, 0x69, 0xF7, 0x53, 0x24,
0x82, 0x0E, 0x8D, 0x49, 0x37, 0xFA, 0xFD, 0xC5, 0x48, 0x76, 0xF0, 0xC0,
0x5D, 0xF1, 0xCA, 0xAC, 0x7C, 0xC4, 0x5E, 0xC0, 0x93, 0x0C, 0x8E, 0x64,
0x7C, 0x57, 0xFE, 0xEB
}
};
static BOOL IsKnownMSWHQLCertFingerprint (const unsigned char hashVal[64])
{
size_t i;
for (i = 0; i < sizeof (gpbSha512MSWHQLCertFingerprints) / sizeof (gpbSha512MSWHQLCertFingerprints[0]); ++i)
{
if (0 == memcmp (hashVal, gpbSha512MSWHQLCertFingerprints[i], 64))
return TRUE;
}
return FALSE;
}
/* Windows dialog class */
#define WINDOWS_DIALOG_CLASS L"#32770"
@@ -944,7 +970,7 @@ cleanup:
}
#endif
BOOL VerifyModuleSignature (const wchar_t* path)
static BOOL VerifyModuleSignatureInternal (const wchar_t* path, BOOL bAllowMicrosoftWHQL)
{
#if defined(NDEBUG) && !defined (VC_SKIP_OS_DRIVER_REQ_CHECK)
BOOL bResult = FALSE;
@@ -995,9 +1021,8 @@ BOOL VerifyModuleSignature (const wchar_t* path)
BYTE hashVal[64];
sha512 (hashVal, pProviderCert->pCert->pbCertEncoded, pProviderCert->pCert->cbCertEncoded);
if ( (0 == memcmp (hashVal, gpbSha512CodeSignCertFingerprint, 64))
|| (0 == memcmp (hashVal, gpbSha512MSCodeSignCertFingerprint, 64))
)
if ((0 == memcmp (hashVal, gpbSha512CodeSignCertFingerprint, 64))
|| (bAllowMicrosoftWHQL && IsKnownMSWHQLCertFingerprint (hashVal)))
{
bResult = TRUE;
}
@@ -1016,6 +1041,16 @@ BOOL VerifyModuleSignature (const wchar_t* path)
#endif
}
BOOL VerifyModuleSignature (const wchar_t* path)
{
return VerifyModuleSignatureInternal (path, FALSE);
}
BOOL VerifyModuleSignatureAllowingMicrosoftWHQL (const wchar_t* path)
{
return VerifyModuleSignatureInternal (path, TRUE);
}
DWORD handleWin32Error (HWND hwndDlg, const char* srcPos)
{
#if !defined(VC_COMREG) && !defined(VCSDK_DLL)

View File

@@ -594,6 +594,7 @@ BOOL DeleteDirectory (const wchar_t* szDirName);
BOOL IsThreadInSecureDesktop(DWORD dwThreadID);
INT_PTR SecureDesktopDialogBoxParam (HINSTANCE, LPCWSTR, HWND, DLGPROC, LPARAM);
BOOL VerifyModuleSignature (const wchar_t* path);
BOOL VerifyModuleSignatureAllowingMicrosoftWHQL (const wchar_t* path);
void GetInstallationPath (HWND hwndDlg, wchar_t* szInstallPath, DWORD cchSize, BOOL* pbInstallPathDetermined);
BOOL GetSetupconfigLocation (wchar_t* path, DWORD cchSize);
BOOL BufferHasPattern (const unsigned char* buffer, size_t bufferLen, const void* pattern, size_t patternLen);

View File

@@ -4941,7 +4941,7 @@ BOOL CALLBACK TravelerDlgProc (HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lPa
// Driver
StringCbPrintfW (srcPath, sizeof(srcPath), L"%s\\veracrypt.sys", appDir);
StringCbPrintfW (dstPath, sizeof(dstPath), L"%s\\VeraCrypt\\veracrypt.sys", dstDir);
if (!VerifyModuleSignature (srcPath))
if (!VerifyModuleSignatureAllowingMicrosoftWHQL (srcPath))
{
Error ("DIST_PACKAGE_CORRUPTED", hwndDlg);
goto stop;
@@ -4955,7 +4955,7 @@ BOOL CALLBACK TravelerDlgProc (HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lPa
// Driver x64
StringCbPrintfW (srcPath, sizeof(srcPath), L"%s\\veracrypt-x64.sys", appDir);
StringCbPrintfW (dstPath, sizeof(dstPath), L"%s\\VeraCrypt\\veracrypt-x64.sys", dstDir);
if (!VerifyModuleSignature (srcPath))
if (!VerifyModuleSignatureAllowingMicrosoftWHQL (srcPath))
{
Error ("DIST_PACKAGE_CORRUPTED", hwndDlg);
goto stop;
@@ -4969,7 +4969,7 @@ BOOL CALLBACK TravelerDlgProc (HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lPa
// Driver ARM64
StringCbPrintfW(srcPath, sizeof(srcPath), L"%s\\veracrypt-arm64.sys", appDir);
StringCbPrintfW(dstPath, sizeof(dstPath), L"%s\\VeraCrypt\\veracrypt-arm64.sys", dstDir);
if (!VerifyModuleSignature(srcPath))
if (!VerifyModuleSignatureAllowingMicrosoftWHQL(srcPath))
{
Error("DIST_PACKAGE_CORRUPTED", hwndDlg);
goto stop;
@@ -4983,19 +4983,23 @@ BOOL CALLBACK TravelerDlgProc (HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lPa
else
{
int fileNo = 0;
BOOL bMsiX64Case = FALSE;
// get file from the Setup binary after checking its signature and its version
BOOL bMsiPackage = FALSE;
BOOL bCopiedX64App = FALSE;
BOOL bCopiedX64Driver = FALSE;
BOOL bCopiedX64Wizard = FALSE;
BOOL bCopiedX64Expander = FALSE;
// Get files from the IDRIX-signed setup or COMReg package after checking its signature and integrity.
StringCbPrintfW (srcPath, sizeof(srcPath), L"%s\\VeraCrypt COMReg.exe", appDir); // MSI installation case
if (FileExists(srcPath))
{
bMsiX64Case = TRUE;
bMsiPackage = TRUE;
}
else
StringCbPrintfW (srcPath, sizeof(srcPath), L"%s\\VeraCrypt Setup.exe", appDir); // EXE installation case
FreeAllFileBuffers ();
if (!VerifyPackageIntegrity (srcPath) || !SelfExtractInMemory (srcPath, TRUE) || (!bMsiX64Case && (Decompressed_Files_Count != NBR_COMPRESSED_FILES)))
if (!VerifyPackageIntegrity (srcPath) || !SelfExtractInMemory (srcPath, TRUE) || (!bMsiPackage && (Decompressed_Files_Count != NBR_COMPRESSED_FILES)))
{
MessageBoxW (hwndDlg, GetString ("DIST_PACKAGE_CORRUPTED"), lpszTitle, MB_ICONEXCLAMATION);
goto stop;
@@ -5071,71 +5075,21 @@ BOOL CALLBACK TravelerDlgProc (HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lPa
MessageBoxW (hwndDlg, szTmp, lpszTitle, MB_ICONERROR | MB_SETFOREGROUND | MB_TOPMOST);
goto stop;
}
if (wcscmp (fileName, L"VeraCrypt-x64.exe") == 0)
bCopiedX64App = TRUE;
else if (wcscmp (fileName, L"veracrypt-x64.sys") == 0)
bCopiedX64Driver = TRUE;
else if (wcscmp (fileName, L"VeraCrypt Format-x64.exe") == 0)
bCopiedX64Wizard = TRUE;
else if (wcscmp (fileName, L"VeraCryptExpander-x64.exe") == 0)
bCopiedX64Expander = TRUE;
}
if (bMsiX64Case)
if (bMsiPackage && (!bCopiedX64App || !bCopiedX64Driver || (copyWizard && !bCopiedX64Wizard) || (copyExpander && !bCopiedX64Expander)))
{
// Main app
StringCbPrintfW (srcPath, sizeof(srcPath), L"%s\\VeraCrypt.exe", appDir);
StringCbPrintfW (dstPath, sizeof(dstPath), L"%s\\VeraCrypt\\VeraCrypt-x64.exe", dstDir);
if (!VerifyModuleSignature (srcPath))
{
Error ("DIST_PACKAGE_CORRUPTED", hwndDlg);
goto stop;
}
else if (!TCCopyFile (srcPath, dstPath))
{
handleWin32Error (hwndDlg, SRC_POS);
goto stop;
}
// Wizard
if (copyWizard)
{
StringCbPrintfW (srcPath, sizeof(srcPath), L"%s\\VeraCrypt Format.exe", appDir);
StringCbPrintfW (dstPath, sizeof(dstPath), L"%s\\VeraCrypt\\VeraCrypt Format-x64.exe", dstDir);
if (!VerifyModuleSignature (srcPath))
{
Error ("DIST_PACKAGE_CORRUPTED", hwndDlg);
goto stop;
}
else if (!TCCopyFile (srcPath, dstPath))
{
handleWin32Error (hwndDlg, SRC_POS);
goto stop;
}
}
// Expander
if (copyExpander)
{
StringCbPrintfW (srcPath, sizeof(srcPath), L"%s\\VeraCryptExpander.exe", appDir);
StringCbPrintfW (dstPath, sizeof(dstPath), L"%s\\VeraCrypt\\VeraCryptExpander-x64.exe", dstDir);
if (!VerifyModuleSignature (srcPath))
{
Error ("DIST_PACKAGE_CORRUPTED", hwndDlg);
goto stop;
}
else if (!TCCopyFile (srcPath, dstPath))
{
handleWin32Error (hwndDlg, SRC_POS);
goto stop;
}
}
// Driver
StringCbPrintfW (srcPath, sizeof(srcPath), L"%s\\veracrypt.sys", appDir);
StringCbPrintfW (dstPath, sizeof(dstPath), L"%s\\VeraCrypt\\veracrypt-x64.sys", dstDir);
if (!VerifyModuleSignature (srcPath))
{
Error ("DIST_PACKAGE_CORRUPTED", hwndDlg);
goto stop;
}
else if (!TCCopyFile (srcPath, dstPath))
{
handleWin32Error (hwndDlg, SRC_POS);
goto stop;
}
MessageBoxW (hwndDlg, GetString ("DIST_PACKAGE_CORRUPTED"), lpszTitle, MB_ICONEXCLAMATION);
goto stop;
}
}