VeraCrypt
aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMounir IDRASSI <mounir.idrassi@idrix.fr>2015-04-05 22:21:59 +0200
committerMounir IDRASSI <mounir.idrassi@idrix.fr>2015-04-06 00:22:36 +0200
commit2784652ab880dcea82aa212096b64d39695012fc (patch)
treeb6cc4636a3e47efaeae338dca1fca87a347b82b8
parenta284922ce45ca777dd98b53e846603c63cb44904 (diff)
downloadVeraCrypt-2784652ab880dcea82aa212096b64d39695012fc.tar.gz
VeraCrypt-2784652ab880dcea82aa212096b64d39695012fc.zip
Windows vulnerability fix: CryptAcquireContext vulnerability fix. Add checks to random generator to abort in case of error and display a diagnose message to the user.
-rw-r--r--src/Common/BootEncryption.cpp25
-rw-r--r--src/Common/Dlgcode.c36
-rw-r--r--src/Common/Dlgcode.h1
-rw-r--r--src/Common/Exception.h33
-rw-r--r--src/Common/Language.xml3
-rw-r--r--src/Common/Password.c6
-rw-r--r--src/Common/Random.c58
-rw-r--r--src/Common/Random.h1
-rw-r--r--src/Common/Tcdefs.h4
-rw-r--r--src/ExpandVolume/DlgExpandVolume.cpp5
-rw-r--r--src/ExpandVolume/ExpandVolume.c8
-rw-r--r--src/Format/Tcformat.c10
-rw-r--r--src/Mount/Mount.c5
13 files changed, 171 insertions, 24 deletions
diff --git a/src/Common/BootEncryption.cpp b/src/Common/BootEncryption.cpp
index c01a8b4b..ae57dc37 100644
--- a/src/Common/BootEncryption.cpp
+++ b/src/Common/BootEncryption.cpp
@@ -1383,7 +1383,12 @@ namespace VeraCrypt
request.WipeAlgorithm = wipeAlgorithm;
if (Randinit() != ERR_SUCCESS)
- throw ParameterIncorrect (SRC_POS);
+ {
+ if (CryptoAPILastError == ERROR_SUCCESS)
+ throw RandInitFailed (SRC_POS, GetLastError ());
+ else
+ throw CryptoApiFailed (SRC_POS, CryptoAPILastError);
+ }
/* force the display of the random enriching dialog */
SetRandomPoolEnrichedByUserStatus (FALSE);
@@ -1421,9 +1426,17 @@ namespace VeraCrypt
void BootEncryption::WipeHiddenOSCreationConfig ()
{
- if (IsHiddenOSRunning() || Randinit() != ERR_SUCCESS)
+ if (IsHiddenOSRunning())
throw ParameterIncorrect (SRC_POS);
+ if (Randinit() != ERR_SUCCESS)
+ {
+ if (CryptoAPILastError == ERROR_SUCCESS)
+ throw RandInitFailed (SRC_POS, GetLastError ());
+ else
+ throw CryptoApiFailed (SRC_POS, CryptoAPILastError);
+ }
+
Device device (GetSystemDriveConfiguration().DevicePath);
device.CheckOpened();
byte mbr[TC_SECTOR_SIZE_BIOS];
@@ -2280,7 +2293,13 @@ namespace VeraCrypt
RandSetHashFunction (pkcs5);
}
- throw_sys_if (Randinit () != 0);
+ if (Randinit() != 0)
+ {
+ if (CryptoAPILastError == ERROR_SUCCESS)
+ throw RandInitFailed (SRC_POS, GetLastError ());
+ else
+ throw CryptoApiFailed (SRC_POS, CryptoAPILastError);
+ }
finally_do ({ RandStop (FALSE); });
/* force the display of the random enriching dialog */
diff --git a/src/Common/Dlgcode.c b/src/Common/Dlgcode.c
index 5f5d2216..94b1fc05 100644
--- a/src/Common/Dlgcode.c
+++ b/src/Common/Dlgcode.c
@@ -461,11 +461,11 @@ int RemoveFakeDosName (char *lpszDiskFile, char *lpszDosDevice)
}
-void AbortProcess (char *stringId)
+void AbortProcessDirect (wchar_t *abortMsg)
{
// Note that this function also causes localcleanup() to be called (see atexit())
MessageBeep (MB_ICONEXCLAMATION);
- MessageBoxW (NULL, GetString (stringId), lpszTitle, ICON_HAND);
+ MessageBoxW (NULL, abortMsg, lpszTitle, ICON_HAND);
if (hRichEditDll)
{
FreeLibrary (hRichEditDll);
@@ -474,6 +474,12 @@ void AbortProcess (char *stringId)
exit (1);
}
+void AbortProcess (char *stringId)
+{
+ // Note that this function also causes localcleanup() to be called (see atexit())
+ AbortProcessDirect (GetString (stringId));
+}
+
void AbortProcessSilent (void)
{
if (hRichEditDll)
@@ -4076,6 +4082,18 @@ void handleError (HWND hwndDlg, int code)
MessageBoxW (hwndDlg, szTmp, lpszTitle, ICON_HAND);
break;
+#ifndef SETUP
+ case ERR_RAND_INIT_FAILED:
+ StringCbPrintfW (szTmp, sizeof(szTmp), GetString ("INIT_RAND"), SRC_POS, GetLastError ());
+ MessageBoxW (hwndDlg, szTmp, lpszTitle, MB_ICONERROR);
+ break;
+
+ case ERR_CAPI_INIT_FAILED:
+ StringCbPrintfW (szTmp, sizeof(szTmp), GetString ("CAPI_RAND"), SRC_POS, CryptoAPILastError);
+ MessageBoxW (hwndDlg, szTmp, lpszTitle, MB_ICONERROR);
+ break;
+#endif
+
default:
StringCbPrintfW (szTmp, sizeof(szTmp), GetString ("ERR_UNKNOWN"), code);
MessageBoxW (hwndDlg, szTmp, lpszTitle, ICON_HAND);
@@ -5009,7 +5027,10 @@ exit:
return 0;
}
-
+/* Randinit is always called before UserEnrichRandomPool, so we don't need
+ * the extra Randinit call here since it will always succeed but we keep it
+ * for clarity purposes
+ */
void UserEnrichRandomPool (HWND hwndDlg)
{
if ((0 == Randinit()) && !IsRandomPoolEnrichedByUser())
@@ -5060,7 +5081,7 @@ BOOL CALLBACK KeyfileGeneratorDlgProc (HWND hwndDlg, UINT msg, WPARAM wParam, LP
#ifndef VOLFORMAT
if (Randinit ())
{
- Error ("INIT_RAND", hwndDlg);
+ handleError (hwndDlg, (CryptoAPILastError == ERROR_SUCCESS)? ERR_RAND_INIT_FAILED : ERR_CAPI_INIT_FAILED);
EndDialog (hwndDlg, IDCLOSE);
}
#endif
@@ -9236,7 +9257,12 @@ int ReEncryptVolumeHeader (HWND hwndDlg, char *buffer, BOOL bBoot, CRYPTO_INFO *
RandSetHashFunction (cryptoInfo->pkcs5);
if (Randinit() != ERR_SUCCESS)
- return ERR_PARAMETER_INCORRECT;
+ {
+ if (CryptoAPILastError == ERROR_SUCCESS)
+ return ERR_RAND_INIT_FAILED;
+ else
+ return ERR_CAPI_INIT_FAILED;
+ }
UserEnrichRandomPool (NULL);
diff --git a/src/Common/Dlgcode.h b/src/Common/Dlgcode.h
index 8f6314eb..96d5e865 100644
--- a/src/Common/Dlgcode.h
+++ b/src/Common/Dlgcode.h
@@ -226,6 +226,7 @@ void UpperCaseCopy ( char *lpszDest , size_t cbDest, const char *lpszSource );
void CreateFullVolumePath ( char *lpszDiskFile , size_t cbDiskFile, const char *lpszFileName , BOOL *bDevice );
int FakeDosNameForDevice ( const char *lpszDiskFile , char *lpszDosDevice , size_t cbDosDevice, char *lpszCFDevice , size_t cbCFDevice, BOOL bNameOnly );
int RemoveFakeDosName ( char *lpszDiskFile , char *lpszDosDevice );
+void AbortProcessDirect ( wchar_t *abortMsg );
void AbortProcess ( char *stringId );
void AbortProcessSilent ( void );
void *err_malloc ( size_t size );
diff --git a/src/Common/Exception.h b/src/Common/Exception.h
index e5d4fd4c..0883df14 100644
--- a/src/Common/Exception.h
+++ b/src/Common/Exception.h
@@ -11,6 +11,7 @@
#include "Platform/PlatformBase.h"
#include "Dlgcode.h"
+#include <strsafe.h>
namespace VeraCrypt
{
@@ -62,6 +63,38 @@ namespace VeraCrypt
const char *SrcPos;
};
+ struct RandInitFailed : public Exception
+ {
+ RandInitFailed (const char *srcPos, DWORD dwLastError) : SrcPos (srcPos), LastError (dwLastError) { }
+
+ void Show (HWND parent) const
+ {
+ char szErrCode[16];
+ StringCbPrintf (szErrCode, sizeof(szErrCode), "0x%.8X", LastError);
+ string msgBody = "The Random Generator initialization failed.\n\n\n(If you report a bug in connection with this, please include the following technical information in the bug report:\n" + string (SrcPos) + "\nLast Error = " + string (szErrCode) + ")";
+ MessageBox (parent, msgBody.c_str(), "VeraCrypt", MB_ICONERROR | MB_SETFOREGROUND);
+ }
+
+ const char *SrcPos;
+ DWORD LastError;
+ };
+
+ struct CryptoApiFailed : public Exception
+ {
+ CryptoApiFailed (const char *srcPos, DWORD dwLastError) : SrcPos (srcPos), LastError (dwLastError) { }
+
+ void Show (HWND parent) const
+ {
+ char szErrCode[16];
+ StringCbPrintf (szErrCode, sizeof(szErrCode), "0x%.8X", LastError);
+ string msgBody = "Windows Crypto API failed.\n\n\n(If you report a bug in connection with this, please include the following technical information in the bug report:\n" + string (SrcPos) + "\nLast Error = " + string (szErrCode) + ")";
+ MessageBox (parent, msgBody.c_str(), "VeraCrypt", MB_ICONERROR | MB_SETFOREGROUND);
+ }
+
+ const char *SrcPos;
+ DWORD LastError;
+ };
+
struct TimeOut : public Exception
{
TimeOut (const char *srcPos) { }
diff --git a/src/Common/Language.xml b/src/Common/Language.xml
index c149b679..c4d93f22 100644
--- a/src/Common/Language.xml
+++ b/src/Common/Language.xml
@@ -526,7 +526,8 @@
<string lang="en" key="CONFIRM_RESTART">Your computer must be restarted.\n\nDo you want to restart it now?</string>
<string lang="en" key="ERR_GETTING_SYSTEM_ENCRYPTION_STATUS">An error occurred when obtaining the system encryption status.</string>
<string lang="en" key="INIT_SYS_ENC">Cannot initialize application components for system encryption.</string>
- <string lang="en" key="INIT_RAND">Failed to initialize the random number generator!</string>
+ <string lang="en" key="INIT_RAND">Failed to initialize the random number generator!\n\n\n(If you report a bug in connection with this, please include the following technical information in the bug report:\n%hs, Last Error = 0x%.8X)</string>
+ <string lang="en" key="CAPI_RAND">Windows Crypto API failed!\n\n\n(If you report a bug in connection with this, please include the following technical information in the bug report:\n%hs, Last Error = 0x%.8X)</string>
<string lang="en" key="INIT_REGISTER">Unable to initialize the application. Failed to register the Dialog class.</string>
<string lang="en" key="INIT_RICHEDIT">Error: Failed to load the Rich Edit system library.</string>
<string lang="en" key="INTRO_TITLE">VeraCrypt Volume Creation Wizard</string>
diff --git a/src/Common/Password.c b/src/Common/Password.c
index b1584dbe..8014713c 100644
--- a/src/Common/Password.c
+++ b/src/Common/Password.c
@@ -230,7 +230,13 @@ int ChangePwd (const char *lpszVolume, Password *oldPassword, int old_pkcs5, BOO
}
if (Randinit ())
+ {
+ if (CryptoAPILastError == ERROR_SUCCESS)
+ nStatus = ERR_RAND_INIT_FAILED;
+ else
+ nStatus = ERR_CAPI_INIT_FAILED;
goto error;
+ }
SetRandomPoolEnrichedByUserStatus (FALSE); /* force the display of the random enriching dialog */
diff --git a/src/Common/Random.c b/src/Common/Random.c
index e8433c27..ae91f2da 100644
--- a/src/Common/Random.c
+++ b/src/Common/Random.c
@@ -60,12 +60,14 @@ HANDLE hNetAPI32 = NULL;
// CryptoAPI
BOOL CryptoAPIAvailable = FALSE;
+DWORD CryptoAPILastError = ERROR_SUCCESS;
HCRYPTPROV hCryptProv;
/* Init the random number generator, setup the hooks, and start the thread */
int Randinit ()
{
+ DWORD dwLastError = ERROR_SUCCESS;
if (GetMaxPkcs5OutSize() > RNG_POOL_SIZE)
TC_THROW_FATAL_EXCEPTION;
@@ -75,6 +77,7 @@ int Randinit ()
InitializeCriticalSection (&critRandProt);
bRandDidInit = TRUE;
+ CryptoAPILastError = ERROR_SUCCESS;
if (pRandPool == NULL)
{
@@ -98,10 +101,13 @@ int Randinit ()
handleWin32Error (0);
goto error;
}
-
- if (!CryptAcquireContext (&hCryptProv, NULL, NULL, PROV_RSA_FULL, 0)
- && !CryptAcquireContext (&hCryptProv, NULL, NULL, PROV_RSA_FULL, CRYPT_NEWKEYSET))
+
+ if (!CryptAcquireContext (&hCryptProv, NULL, MS_ENHANCED_PROV, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT | CRYPT_SILENT))
+ {
CryptoAPIAvailable = FALSE;
+ CryptoAPILastError = GetLastError ();
+ goto error;
+ }
else
CryptoAPIAvailable = TRUE;
@@ -111,7 +117,9 @@ int Randinit ()
return 0;
error:
+ dwLastError = GetLastError();
RandStop (TRUE);
+ SetLastError (dwLastError);
return 1;
}
@@ -149,6 +157,7 @@ void RandStop (BOOL freePool)
{
CryptReleaseContext (hCryptProv, 0);
CryptoAPIAvailable = FALSE;
+ CryptoAPILastError = ERROR_SUCCESS;
}
hMouse = NULL;
@@ -359,13 +368,19 @@ BOOL RandgetBytesFull ( void* hwndDlg, unsigned char *buf , int len, BOOL forceS
if (bDidSlowPoll == FALSE || forceSlowPoll)
{
if (!SlowPoll ())
+ {
+ handleError ((HWND) hwndDlg, ERR_CAPI_INIT_FAILED);
ret = FALSE;
+ }
else
bDidSlowPoll = TRUE;
}
if (!FastPoll ())
+ {
+ handleError ((HWND) hwndDlg, ERR_CAPI_INIT_FAILED);
ret = FALSE;
+ }
/* There's never more than RNG_POOL_SIZE worth of randomess */
if ( (!allowAnyLength) && (len > RNG_POOL_SIZE))
@@ -692,13 +707,24 @@ BOOL SlowPoll (void)
CloseHandle (hDevice);
}
- // CryptoAPI
- if (CryptoAPIAvailable && CryptGenRandom (hCryptProv, sizeof (buffer), buffer))
+ // CryptoAPI: We always have a valid CryptoAPI context when we arrive here but
+ // we keep the check for clarity purpose
+ if ( !CryptoAPIAvailable )
+ return FALSE;
+ if (CryptGenRandom (hCryptProv, sizeof (buffer), buffer))
+ {
RandaddBuf (buffer, sizeof (buffer));
- burn(buffer, sizeof (buffer));
- Randmix();
- return TRUE;
+ burn(buffer, sizeof (buffer));
+ Randmix();
+ return TRUE;
+ }
+ else
+ {
+ /* return error in case CryptGenRandom fails */
+ CryptoAPILastError = GetLastError ();
+ return FALSE;
+ }
}
@@ -803,9 +829,21 @@ BOOL FastPoll (void)
RandaddBuf ((unsigned char *) &dwTicks, sizeof (dwTicks));
}
- // CryptoAPI
- if (CryptoAPIAvailable && CryptGenRandom (hCryptProv, sizeof (buffer), buffer))
+ // CryptoAPI: We always have a valid CryptoAPI context when we arrive here but
+ // we keep the check for clarity purpose
+ if ( !CryptoAPIAvailable )
+ return FALSE;
+ if (CryptGenRandom (hCryptProv, sizeof (buffer), buffer))
+ {
RandaddBuf (buffer, sizeof (buffer));
+ burn (buffer, sizeof(buffer));
+ }
+ else
+ {
+ /* return error in case CryptGenRandom fails */
+ CryptoAPILastError = GetLastError ();
+ return FALSE;
+ }
/* Apply the pool mixing function */
Randmix();
diff --git a/src/Common/Random.h b/src/Common/Random.h
index 72427e07..65e793fa 100644
--- a/src/Common/Random.h
+++ b/src/Common/Random.h
@@ -58,6 +58,7 @@ BOOL RandgetBytesFull ( void* hwndDlg, unsigned char *buf , int len, BOOL forceS
extern BOOL volatile bFastPollEnabled;
extern BOOL volatile bRandmixEnabled;
+extern DWORD CryptoAPILastError;
LRESULT CALLBACK MouseProc ( int nCode , WPARAM wParam , LPARAM lParam );
LRESULT CALLBACK KeyboardProc ( int nCode , WPARAM wParam , LPARAM lParam );
diff --git a/src/Common/Tcdefs.h b/src/Common/Tcdefs.h
index e177e02c..63dff857 100644
--- a/src/Common/Tcdefs.h
+++ b/src/Common/Tcdefs.h
@@ -301,7 +301,9 @@ enum
ERR_SYS_HIDVOL_HEAD_REENC_MODE_WRONG = 31,
ERR_NONSYS_INPLACE_ENC_INCOMPLETE = 32,
ERR_USER_ABORT = 33,
- ERR_UNSUPPORTED_TRUECRYPT_FORMAT = 34
+ ERR_UNSUPPORTED_TRUECRYPT_FORMAT = 34,
+ ERR_RAND_INIT_FAILED = 35,
+ ERR_CAPI_INIT_FAILED = 36
};
#endif // #ifndef TCDEFS_H
diff --git a/src/ExpandVolume/DlgExpandVolume.cpp b/src/ExpandVolume/DlgExpandVolume.cpp
index 966650bb..db2aa9fd 100644
--- a/src/ExpandVolume/DlgExpandVolume.cpp
+++ b/src/ExpandVolume/DlgExpandVolume.cpp
@@ -476,7 +476,10 @@ void ExpandVolumeWizard (HWND hwndDlg, char *lpszVolume)
}
if (Randinit() != ERR_SUCCESS) {
- nStatus = ERR_PARAMETER_INCORRECT;
+ if (CryptoAPILastError == ERROR_SUCCESS)
+ nStatus = ERR_RAND_INIT_FAILED;
+ else
+ nStatus = ERR_CAPI_INIT_FAILED;
goto error;
}
diff --git a/src/ExpandVolume/ExpandVolume.c b/src/ExpandVolume/ExpandVolume.c
index 65a3740a..1d777a11 100644
--- a/src/ExpandVolume/ExpandVolume.c
+++ b/src/ExpandVolume/ExpandVolume.c
@@ -602,7 +602,13 @@ static int ExpandVolume (HWND hwndDlg, char *lpszVolume, Password *pVolumePasswo
}
if (Randinit ())
- goto error; // note: nStatus == ERR_OS_ERROR
+ {
+ if (CryptoAPILastError == ERROR_SUCCESS)
+ nStatus = ERR_RAND_INIT_FAILED;
+ else
+ nStatus = ERR_CAPI_INIT_FAILED;
+ goto error;
+ }
if (!bDevice && bPreserveTimestamp)
{
diff --git a/src/Format/Tcformat.c b/src/Format/Tcformat.c
index 80fc6d00..b32ce0ce 100644
--- a/src/Format/Tcformat.c
+++ b/src/Format/Tcformat.c
@@ -9000,7 +9000,15 @@ int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance, char *lpszComm
nPbar = IDC_PROGRESS_BAR;
if (Randinit ())
- AbortProcess ("INIT_RAND");
+ {
+ DWORD dwLastError = GetLastError ();
+ wchar_t szTmp[4096];
+ if (CryptoAPILastError == ERROR_SUCCESS)
+ StringCbPrintfW (szTmp, sizeof(szTmp), GetString ("INIT_RAND"), SRC_POS, dwLastError);
+ else
+ StringCbPrintfW (szTmp, sizeof(szTmp), GetString ("CAPI_RAND"), SRC_POS, CryptoAPILastError);
+ AbortProcessDirect (szTmp);
+ }
RegisterRedTick(hInstance);
diff --git a/src/Mount/Mount.c b/src/Mount/Mount.c
index 3e567541..fad9d4e9 100644
--- a/src/Mount/Mount.c
+++ b/src/Mount/Mount.c
@@ -8199,7 +8199,10 @@ noHidden:
if (Randinit() != ERR_SUCCESS)
{
- nStatus = ERR_PARAMETER_INCORRECT;
+ if (CryptoAPILastError == ERROR_SUCCESS)
+ nStatus = ERR_RAND_INIT_FAILED;
+ else
+ nStatus = ERR_CAPI_INIT_FAILED;
goto error;
}