From 60575d9a496bd4b796bab73888b69c249a1f8048 Mon Sep 17 00:00:00 2001 From: Mounir IDRASSI Date: Fri, 8 Apr 2016 23:51:29 +0200 Subject: Windows: start implementation of volume ID mechanism that will be used to identify VeraCrypt disk volumes instead of device name. --- src/Common/Apidrvr.h | 5 ++ src/Common/Dlgcode.c | 219 +++++++++++++++++++++++++++++++++++++++++++----- src/Common/Dlgcode.h | 6 +- src/Common/Language.xml | 3 + 4 files changed, 210 insertions(+), 23 deletions(-) (limited to 'src/Common') diff --git a/src/Common/Apidrvr.h b/src/Common/Apidrvr.h index 2cfa369f..867366b9 100644 --- a/src/Common/Apidrvr.h +++ b/src/Common/Apidrvr.h @@ -128,6 +128,7 @@ typedef struct unsigned __int32 ulMountedDrives; /* Bitfield of all mounted drive letters */ wchar_t wszVolume[26][TC_MAX_PATH]; /* Volume names of mounted volumes */ wchar_t wszLabel[26][33]; /* Labels of mounted volumes */ + wchar_t volumeID[26][SHA512_DIGEST_SIZE]; /* IDs of mounted volumes */ unsigned __int64 diskLength[26]; int ea[26]; int volumeType[26]; /* Volume type (e.g. PROP_VOL_TYPE_OUTER, PROP_VOL_TYPE_OUTER_VOL_WRITE_PREVENTED, etc.) */ @@ -156,6 +157,7 @@ typedef struct int volumePim; wchar_t wszLabel[33]; BOOL bDriverSetLabel; + unsigned char volumeID[SHA512_DIGESTSIZE]; } VOLUME_PROPERTIES_STRUCT; typedef struct @@ -194,6 +196,9 @@ typedef struct BOOL TCBootLoaderDetected; BOOL DetectFilesystem; BOOL FilesystemDetected; + BOOL bMatchVolumeID; + unsigned char volumeID[SHA512_DIGEST_SIZE]; + BOOL VolumeIDMatched; } OPEN_TEST_STRUCT; diff --git a/src/Common/Dlgcode.c b/src/Common/Dlgcode.c index 749caa40..02d9b499 100644 --- a/src/Common/Dlgcode.c +++ b/src/Common/Dlgcode.c @@ -2930,7 +2930,7 @@ void InitHelpFileName (void) } } -BOOL OpenDevice (const wchar_t *lpszPath, OPEN_TEST_STRUCT *driver, BOOL detectFilesystem) +BOOL OpenDevice (const wchar_t *lpszPath, OPEN_TEST_STRUCT *driver, BOOL detectFilesystem, BOOL matchVolumeID, BYTE* pbVolumeID) { DWORD dwResult; BOOL bResult; @@ -2943,6 +2943,9 @@ BOOL OpenDevice (const wchar_t *lpszPath, OPEN_TEST_STRUCT *driver, BOOL detectF driver->bDetectTCBootLoader = FALSE; driver->DetectFilesystem = detectFilesystem; + driver->bMatchVolumeID = matchVolumeID; + if (matchVolumeID && pbVolumeID) + memcpy (driver->volumeID, pbVolumeID, SHA512_DIGEST_SIZE); bResult = DeviceIoControl (hDriver, TC_IOCTL_OPEN_TEST, driver, sizeof (OPEN_TEST_STRUCT), @@ -4712,6 +4715,55 @@ wstring IntToWideString (int val) return szTmp; } +wstring ArrayToHexWideString (const unsigned char* pbData, int cbData) +{ + static wchar_t* hexChar = L"0123456789ABCDEF"; + wstring result; + if (pbData) + { + for (int i = 0; i < cbData; i++) + { + result += hexChar[pbData[i] >> 4]; + result += hexChar[pbData[i] & 0x0F]; + } + } + + return result; +} + +bool HexToByte (wchar_t c, byte& b) +{ + bool bRet = true; + if (c >= L'0' && c <= L'9') + b = (byte) (c - L'0'); + else if (c >= L'a' && c <= L'z') + b = (byte) (c - L'a' + 10); + else if (c >= L'A' && c <= L'Z') + b = (byte) (c - L'A' + 10); + else + bRet = false; + + return bRet; +} + +bool HexWideStringToArray (const wchar_t* hexStr, std::vector& arr) +{ + byte b1, b2; + size_t i, len = wcslen (hexStr); + + arr.clear(); + if (len %2) + return false; + + for (i = 0; i < len/2; i++) + { + if (!HexToByte (*hexStr++, b1) || !HexToByte (*hexStr++, b2)) + return false; + arr.push_back (b1 << 4 | b2); + } + return true; +} + wstring GetTempPathString () { wchar_t tempPath[MAX_PATH]; @@ -7069,12 +7121,37 @@ void ShowWaitDialog(HWND hwnd, BOOL bUseHwndAsParent, WaitThreadProc callback, v /************************************************************************/ +static BOOL PerformMountIoctl (MOUNT_STRUCT* pmount, LPDWORD pdwResult, BOOL useVolumeID, BYTE volumeID[SHA512_DIGEST_SIZE]) +{ + if (useVolumeID) + { + wstring devicePath = FindDeviceByVolumeID (volumeID); + if (devicePath == L"") + { + if (pdwResult) + *pdwResult = 0; + SetLastError (ERROR_PATH_NOT_FOUND); + return FALSE; + } + else + { + BOOL bDevice = FALSE; + CreateFullVolumePath (pmount->wszVolume, sizeof(pmount->wszVolume), devicePath.c_str(), &bDevice); + } + } + + return DeviceIoControl (hDriver, TC_IOCTL_MOUNT_VOLUME, pmount, + sizeof (MOUNT_STRUCT), pmount, sizeof (MOUNT_STRUCT), pdwResult, NULL); +} + // specific definitions and implementation for support of mount operation // in wait dialog mechanism typedef struct { MOUNT_STRUCT* pmount; + BOOL useVolumeID; + BYTE volumeID[SHA512_DIGEST_SIZE]; BOOL* pbResult; DWORD* pdwResult; DWORD dwLastError; @@ -7084,8 +7161,7 @@ void CALLBACK MountWaitThreadProc(void* pArg, HWND ) { MountThreadParam* pThreadParam = (MountThreadParam*) pArg; - *(pThreadParam->pbResult) = DeviceIoControl (hDriver, TC_IOCTL_MOUNT_VOLUME, pThreadParam->pmount, - sizeof (MOUNT_STRUCT),pThreadParam->pmount, sizeof (MOUNT_STRUCT), pThreadParam->pdwResult, NULL); + *(pThreadParam->pbResult) = PerformMountIoctl (pThreadParam->pmount, pThreadParam->pdwResult, pThreadParam->useVolumeID, pThreadParam->volumeID); pThreadParam->dwLastError = GetLastError (); } @@ -7122,6 +7198,8 @@ int MountVolume (HWND hwndDlg, BOOL bResult, bDevice; wchar_t root[MAX_PATH]; int favoriteMountOnArrivalRetryCount = 0; + BOOL useVolumeID = FALSE; + BYTE volumeID[SHA512_DIGEST_SIZE] = {0}; #ifdef TCMOUNT if (mountOptions->PartitionInInactiveSysEncScope) @@ -7208,7 +7286,29 @@ retry: StringCchCopyW (volumePath, TC_MAX_PATH, resolvedPath.c_str()); } - CreateFullVolumePath (mount.wszVolume, sizeof(mount.wszVolume), volumePath, &bDevice); + if ((path.length () >= 3) && (_wcsnicmp (path.c_str(), L"ID:", 3) == 0)) + { + std::vector arr; + if ( (path.length() == (3 + 2*SHA512_DIGEST_SIZE)) + && HexWideStringToArray (path.c_str() + 3, arr) + && (arr.size() == SHA512_DIGEST_SIZE) + ) + { + useVolumeID = TRUE; + bDevice = TRUE; + memcpy (volumeID, &arr[0], SHA512_DIGEST_SIZE); + } + else + { + if (!quiet) + Error ("VOLUME_ID_INVALID", hwndDlg); + + SetLastError (ERROR_INVALID_PARAMETER); + return -1; + } + } + else + CreateFullVolumePath (mount.wszVolume, sizeof(mount.wszVolume), volumePath, &bDevice); if (!bDevice) { @@ -7284,6 +7384,8 @@ retry: { MountThreadParam mountThreadParam; mountThreadParam.pmount = &mount; + mountThreadParam.useVolumeID = useVolumeID; + memcpy (mountThreadParam.volumeID, volumeID, SHA512_DIGESTSIZE); mountThreadParam.pbResult = &bResult; mountThreadParam.pdwResult = &dwResult; mountThreadParam.dwLastError = ERROR_SUCCESS; @@ -7294,8 +7396,8 @@ retry: } else { - bResult = DeviceIoControl (hDriver, TC_IOCTL_MOUNT_VOLUME, &mount, - sizeof (mount), &mount, sizeof (mount), &dwResult, NULL); + bResult = PerformMountIoctl (&mount, &dwResult, useVolumeID, volumeID); + dwLastError = GetLastError (); } @@ -7588,25 +7690,40 @@ BOOL IsMountedVolume (const wchar_t *volname) MOUNT_LIST_STRUCT mlist; DWORD dwResult; int i; - wchar_t volume[TC_MAX_PATH*2+16]; - - StringCbCopyW (volume, sizeof(volume), volname); - - if (wcsstr (volname, L"\\Device\\") != volname) - StringCbPrintfW(volume, sizeof(volume), L"\\??\\%s", volname); - - wstring resolvedPath = VolumeGuidPathToDevicePath (volname); - if (!resolvedPath.empty()) - StringCbCopyW (volume, sizeof (volume), resolvedPath.c_str()); memset (&mlist, 0, sizeof (mlist)); DeviceIoControl (hDriver, TC_IOCTL_GET_MOUNTED_VOLUMES, &mlist, sizeof (mlist), &mlist, sizeof (mlist), &dwResult, NULL); - for (i=0 ; i<26; i++) - if (0 == _wcsicmp ((wchar_t *) mlist.wszVolume[i], volume)) - return TRUE; + if ((wcslen (volname) == (3 + 2*SHA512_DIGEST_SIZE)) && _wcsnicmp (volname, L"ID:", 3) == 0) + { + /* Volume ID specified. Use it for matching mounted volumes. */ + std::vector arr; + if (HexWideStringToArray (&volname[3], arr) && (arr.size() == SHA512_DIGEST_SIZE)) + { + for (i=0 ; i<26; i++) + if (0 == memcmp (mlist.volumeID[i], &arr[0], SHA512_DIGEST_SIZE)) + return TRUE; + } + } + else + { + wchar_t volume[TC_MAX_PATH*2+16]; + + StringCbCopyW (volume, sizeof(volume), volname); + + if (wcsstr (volname, L"\\Device\\") != volname) + StringCbPrintfW(volume, sizeof(volume), L"\\??\\%s", volname); + + wstring resolvedPath = VolumeGuidPathToDevicePath (volname); + if (!resolvedPath.empty()) + StringCbCopyW (volume, sizeof (volume), resolvedPath.c_str()); + + for (i=0 ; i<26; i++) + if (0 == _wcsicmp ((wchar_t *) mlist.wszVolume[i], volume)) + return TRUE; + } return FALSE; } @@ -10875,7 +10992,7 @@ std::vector GetAvailableHostDevices (bool noDeviceProperties, bool const wchar_t *devPath = devPathStr.c_str(); OPEN_TEST_STRUCT openTest = {0}; - if (!OpenDevice (devPath, &openTest, detectUnencryptedFilesystems && partNumber != 0)) + if (!OpenDevice (devPath, &openTest, detectUnencryptedFilesystems && partNumber != 0, FALSE, NULL)) { if (partNumber == 0) break; @@ -10980,7 +11097,7 @@ std::vector GetAvailableHostDevices (bool noDeviceProperties, bool const wchar_t *devPath = devPathStr.c_str(); OPEN_TEST_STRUCT openTest = {0}; - if (!OpenDevice (devPath, &openTest, detectUnencryptedFilesystems)) + if (!OpenDevice (devPath, &openTest, detectUnencryptedFilesystems, FALSE, NULL)) continue; DISK_PARTITION_INFO_STRUCT info; @@ -11020,6 +11137,30 @@ std::vector GetAvailableHostDevices (bool noDeviceProperties, bool return devices; } +wstring FindDeviceByVolumeID (BYTE volumeID [SHA512_DIGEST_SIZE]) +{ + for (int devNumber = 0; devNumber < MAX_HOST_DRIVE_NUMBER; devNumber++) + { + for (int partNumber = 0; partNumber < MAX_HOST_PARTITION_NUMBER; partNumber++) + { + wstringstream strm; + strm << L"\\Device\\Harddisk" << devNumber << L"\\Partition" << partNumber; + wstring devPathStr (strm.str()); + const wchar_t *devPath = devPathStr.c_str(); + + OPEN_TEST_STRUCT openTest = {0}; + if (!OpenDevice (devPath, &openTest, FALSE, TRUE, volumeID)) + { + continue; + } + + if (openTest.VolumeIDMatched) + return devPath; + } + } + + return L""; +} BOOL FileHasReadOnlyAttribute (const wchar_t *path) { @@ -11241,8 +11382,25 @@ BOOL VolumePathExists (const wchar_t *volumePath) UpperCaseCopy (upperCasePath, sizeof(upperCasePath), volumePath); + if (wcsstr (upperCasePath, L"ID:") == upperCasePath) + { + std::vector arr; + if ( (wcslen (upperCasePath) == (3 + 2*SHA512_DIGEST_SIZE)) + && HexWideStringToArray (&upperCasePath[3], arr) + && (arr.size() == SHA512_DIGEST_SIZE) + ) + { + if (FindDeviceByVolumeID (&arr[0]).length() > 0) + return TRUE; + else + return FALSE; + } + else + return FALSE; + } + if (wcsstr (upperCasePath, L"\\DEVICE\\") == upperCasePath) - return OpenDevice (volumePath, &openTest, FALSE); + return OpenDevice (volumePath, &openTest, FALSE, FALSE, NULL); wstring path = volumePath; if (path.find (L"\\\\?\\Volume{") == 0 && path.rfind (L"}\\") == path.size() - 2) @@ -11610,3 +11768,20 @@ void AllowMessageInUIPI (UINT msg) ChangeWindowMessageFilterFn (msg, MSGFLT_ADD); } } + +BOOL IsRepeatedByteArray (byte value, const byte* buffer, size_t bufferSize) +{ + if (buffer && bufferSize) + { + size_t i; + for (i = 0; i < bufferSize; i++) + { + if (*buffer++ != value) + return FALSE; + } + return TRUE; + } + else + return FALSE; +} + diff --git a/src/Common/Dlgcode.h b/src/Common/Dlgcode.h index ef00871e..a2f69bad 100644 --- a/src/Common/Dlgcode.h +++ b/src/Common/Dlgcode.h @@ -298,7 +298,7 @@ void InitOSVersionInfo (); void InitApp ( HINSTANCE hInstance, wchar_t *lpszCommandLine ); void FinalizeApp (void); void InitHelpFileName (void); -BOOL OpenDevice (const wchar_t *lpszPath, OPEN_TEST_STRUCT *driver, BOOL detectFilesystem); +BOOL OpenDevice (const wchar_t *lpszPath, OPEN_TEST_STRUCT *driver, BOOL detectFilesystem, BOOL matchVolumeID, BYTE* pbVolumeID); void NotifyDriverOfPortableMode (void); int GetAvailableFixedDisks ( HWND hComboBox , char *lpszRootPath ); int GetAvailableRemovables ( HWND hComboBox , char *lpszRootPath ); @@ -501,6 +501,7 @@ int AddBitmapToImageList(HIMAGELIST himl, HBITMAP hbmImage, HBITMAP hbmMask); HRESULT VCStrDupW(LPCWSTR psz, LPWSTR *ppwsz); void ProcessEntropyEstimate (HWND hProgress, DWORD* pdwInitialValue, DWORD dwCounter, DWORD dwMaxLevel, DWORD* pdwEntropy); void AllowMessageInUIPI (UINT msg); +BOOL IsRepeatedByteArray (byte value, const byte* buffer, size_t bufferSize); #ifdef __cplusplus } @@ -565,6 +566,9 @@ std::wstring HarddiskVolumePathToPartitionPath (const std::wstring &harddiskVolu std::wstring FindLatestFileOrDirectory (const std::wstring &directory, const wchar_t *namePattern, bool findDirectory, bool findFile); std::wstring GetUserFriendlyVersionString (int version); std::wstring IntToWideString (int val); +std::wstring ArrayToHexWideString (const unsigned char* pbData, int cbData); +bool HexWideStringToArray (const wchar_t* hexStr, std::vector& arr); +std::wstring FindDeviceByVolumeID (BYTE volumeID [SHA512_DIGEST_SIZE]); void RegisterDriverInf (bool registerFilter, const std::string& filter, const std::string& filterReg, HWND ParentWindow, HKEY regKey); std::wstring GetTempPathString (); inline std::wstring AppendSrcPos (const wchar_t* msg, const char* srcPos) diff --git a/src/Common/Language.xml b/src/Common/Language.xml index d994bf63..42be6bd4 100644 --- a/src/Common/Language.xml +++ b/src/Common/Language.xml @@ -1388,6 +1388,9 @@ Error: Failed to load a system library. The volume file size specified in the command line is incompatible with selected exFAT filesystem. Randomness Collected From Mouse Movements + Volume ID: + Use Volume ID to mount favorite + The Volume ID value is invalid -- cgit v1.2.3