From 4fa4d6d22708231a51bdff93ef3220aa95b6fc80 Mon Sep 17 00:00:00 2001 From: Mounir IDRASSI Date: Sun, 31 Aug 2014 23:56:37 +0200 Subject: Windows vulnerability fix: correct possible BSOD attack targeted towards GetWipePassCount() / WipeBuffer() found by the Open Crypto Audit Project. --- src/Common/BootEncryption.cpp | 2 +- src/Common/Password.c | 7 +++++++ src/Common/Wipe.c | 13 ++++++++----- src/Driver/DriveFilter.c | 20 +++++++++++++++++--- src/Format/InPlace.c | 10 +++++++++- 5 files changed, 42 insertions(+), 10 deletions(-) diff --git a/src/Common/BootEncryption.cpp b/src/Common/BootEncryption.cpp index e57a434e..9f848fc7 100644 --- a/src/Common/BootEncryption.cpp +++ b/src/Common/BootEncryption.cpp @@ -2064,7 +2064,7 @@ namespace VeraCrypt { BootEncryptionStatus encStatus = GetStatus(); - if (encStatus.SetupInProgress) + if (encStatus.SetupInProgress || (wipePassCount <= 0)) throw ParameterIncorrect (SRC_POS); SystemDriveConfiguration config = GetSystemDriveConfiguration (); diff --git a/src/Common/Password.c b/src/Common/Password.c index c23bd4fa..b1fa83ef 100644 --- a/src/Common/Password.c +++ b/src/Common/Password.c @@ -143,6 +143,13 @@ int ChangePwd (const char *lpszVolume, Password *oldPassword, Password *newPassw if (oldPassword->Length == 0 || newPassword->Length == 0) return -1; + if (wipePassCount <= 0) + { + nStatus = ERR_PARAMETER_INCORRECT; + handleError (hwndDlg, nStatus); + return nStatus; + } + if (!lpszVolume) { nStatus = ERR_OUTOFMEMORY; diff --git a/src/Common/Wipe.c b/src/Common/Wipe.c index f06862e2..d2ee175b 100644 --- a/src/Common/Wipe.c +++ b/src/Common/Wipe.c @@ -157,12 +157,9 @@ int GetWipePassCount (WipeAlgorithmId algorithm) case TC_WIPE_256: return 256; - - default: - TC_THROW_FATAL_EXCEPTION; } - return 0; // Prevent compiler warnings + return -1; // Prevent compiler warnings } @@ -183,8 +180,14 @@ BOOL WipeBuffer (WipeAlgorithmId algorithm, byte randChars[TC_WIPE_RAND_CHAR_COU case TC_WIPE_35_GUTMANN: return Wipe35Gutmann (pass, buffer, size); + /* we will never reach here because all calls to WipeBuffer are preceeded + * by a call to GetWipePassCount that already checks the same algorithm + * parameters and in case of unsupported value an error is returned before + * calling WipeBuffer + */ + /* default: - TC_THROW_FATAL_EXCEPTION; + TC_THROW_FATAL_EXCEPTION;*/ } return FALSE; // Prevent compiler warnings diff --git a/src/Driver/DriveFilter.c b/src/Driver/DriveFilter.c index 331b3720..26fed73d 100644 --- a/src/Driver/DriveFilter.c +++ b/src/Driver/DriveFilter.c @@ -1320,7 +1320,14 @@ static VOID SetupThreadProc (PVOID threadArg) if (SetupRequest.WipeAlgorithm != TC_WIPE_NONE) { byte wipePass; - for (wipePass = 1; wipePass <= GetWipePassCount (SetupRequest.WipeAlgorithm); ++wipePass) + int wipePassCount = GetWipePassCount (SetupRequest.WipeAlgorithm); + if (wipePassCount <= 0) + { + SetupResult = STATUS_INVALID_PARAMETER; + goto err; + } + + for (wipePass = 1; wipePass <= wipePassCount; ++wipePass) { if (!WipeBuffer (SetupRequest.WipeAlgorithm, wipeRandChars, wipePass, wipeBuffer, setupBlockSize)) { @@ -1692,7 +1699,7 @@ static VOID DecoySystemWipeThreadProc (PVOID threadArg) byte *wipeBuffer = NULL; byte *wipeRandBuffer = NULL; byte wipeRandChars[TC_WIPE_RAND_CHAR_COUNT]; - int wipePass; + int wipePass, wipePassCount; int ea = Extension->Queue.CryptoInfo->ea; KIRQL irql; @@ -1755,7 +1762,14 @@ static VOID DecoySystemWipeThreadProc (PVOID threadArg) if (offset.QuadPart > Extension->ConfiguredEncryptedAreaEnd) break; - for (wipePass = 1; wipePass <= GetWipePassCount (WipeDecoyRequest.WipeAlgorithm); ++wipePass) + wipePassCount = GetWipePassCount (WipeDecoyRequest.WipeAlgorithm); + if (wipePassCount <= 0) + { + DecoySystemWipeResult = STATUS_INVALID_PARAMETER; + goto err; + } + + for (wipePass = 1; wipePass <= wipePassCount; ++wipePass) { if (!WipeBuffer (WipeDecoyRequest.WipeAlgorithm, wipeRandChars, wipePass, wipeBuffer, wipeBlockSize)) { diff --git a/src/Format/InPlace.c b/src/Format/InPlace.c index b1bfac98..5c8cb3b4 100644 --- a/src/Format/InPlace.c +++ b/src/Format/InPlace.c @@ -861,10 +861,18 @@ inplace_enc_read: if (wipeAlgorithm != TC_WIPE_NONE) { byte wipePass; + int wipePassCount = GetWipePassCount (wipeAlgorithm); + + if (wipePassCount <= 0) + { + SetLastError (ERROR_INVALID_PARAMETER); + nStatus = ERR_PARAMETER_INCORRECT; + goto closing_seq; + } offset.QuadPart = masterCryptoInfo->EncryptedAreaStart.Value - workChunkSize; - for (wipePass = 1; wipePass <= GetWipePassCount (wipeAlgorithm); ++wipePass) + for (wipePass = 1; wipePass <= wipePassCount; ++wipePass) { if (!WipeBuffer (wipeAlgorithm, wipeRandChars, wipePass, wipeBuffer, workChunkSize)) { -- cgit v1.2.3