1
0
mirror of https://github.com/veracrypt/VeraCrypt.git synced 2025-11-11 11:08:02 -06:00

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.

This commit is contained in:
Mounir IDRASSI
2015-04-05 22:21:59 +02:00
parent a284922ce4
commit 2784652ab8
13 changed files with 171 additions and 24 deletions

View File

@@ -1383,7 +1383,12 @@ namespace VeraCrypt
request.WipeAlgorithm = wipeAlgorithm; request.WipeAlgorithm = wipeAlgorithm;
if (Randinit() != ERR_SUCCESS) 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 */ /* force the display of the random enriching dialog */
SetRandomPoolEnrichedByUserStatus (FALSE); SetRandomPoolEnrichedByUserStatus (FALSE);
@@ -1421,9 +1426,17 @@ namespace VeraCrypt
void BootEncryption::WipeHiddenOSCreationConfig () void BootEncryption::WipeHiddenOSCreationConfig ()
{ {
if (IsHiddenOSRunning() || Randinit() != ERR_SUCCESS) if (IsHiddenOSRunning())
throw ParameterIncorrect (SRC_POS); 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 device (GetSystemDriveConfiguration().DevicePath);
device.CheckOpened(); device.CheckOpened();
byte mbr[TC_SECTOR_SIZE_BIOS]; byte mbr[TC_SECTOR_SIZE_BIOS];
@@ -2280,7 +2293,13 @@ namespace VeraCrypt
RandSetHashFunction (pkcs5); 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); }); finally_do ({ RandStop (FALSE); });
/* force the display of the random enriching dialog */ /* force the display of the random enriching dialog */

View File

@@ -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()) // Note that this function also causes localcleanup() to be called (see atexit())
MessageBeep (MB_ICONEXCLAMATION); MessageBeep (MB_ICONEXCLAMATION);
MessageBoxW (NULL, GetString (stringId), lpszTitle, ICON_HAND); MessageBoxW (NULL, abortMsg, lpszTitle, ICON_HAND);
if (hRichEditDll) if (hRichEditDll)
{ {
FreeLibrary (hRichEditDll); FreeLibrary (hRichEditDll);
@@ -474,6 +474,12 @@ void AbortProcess (char *stringId)
exit (1); exit (1);
} }
void AbortProcess (char *stringId)
{
// Note that this function also causes localcleanup() to be called (see atexit())
AbortProcessDirect (GetString (stringId));
}
void AbortProcessSilent (void) void AbortProcessSilent (void)
{ {
if (hRichEditDll) if (hRichEditDll)
@@ -4076,6 +4082,18 @@ void handleError (HWND hwndDlg, int code)
MessageBoxW (hwndDlg, szTmp, lpszTitle, ICON_HAND); MessageBoxW (hwndDlg, szTmp, lpszTitle, ICON_HAND);
break; 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: default:
StringCbPrintfW (szTmp, sizeof(szTmp), GetString ("ERR_UNKNOWN"), code); StringCbPrintfW (szTmp, sizeof(szTmp), GetString ("ERR_UNKNOWN"), code);
MessageBoxW (hwndDlg, szTmp, lpszTitle, ICON_HAND); MessageBoxW (hwndDlg, szTmp, lpszTitle, ICON_HAND);
@@ -5009,7 +5027,10 @@ exit:
return 0; 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) void UserEnrichRandomPool (HWND hwndDlg)
{ {
if ((0 == Randinit()) && !IsRandomPoolEnrichedByUser()) if ((0 == Randinit()) && !IsRandomPoolEnrichedByUser())
@@ -5060,7 +5081,7 @@ BOOL CALLBACK KeyfileGeneratorDlgProc (HWND hwndDlg, UINT msg, WPARAM wParam, LP
#ifndef VOLFORMAT #ifndef VOLFORMAT
if (Randinit ()) if (Randinit ())
{ {
Error ("INIT_RAND", hwndDlg); handleError (hwndDlg, (CryptoAPILastError == ERROR_SUCCESS)? ERR_RAND_INIT_FAILED : ERR_CAPI_INIT_FAILED);
EndDialog (hwndDlg, IDCLOSE); EndDialog (hwndDlg, IDCLOSE);
} }
#endif #endif
@@ -9236,7 +9257,12 @@ int ReEncryptVolumeHeader (HWND hwndDlg, char *buffer, BOOL bBoot, CRYPTO_INFO *
RandSetHashFunction (cryptoInfo->pkcs5); RandSetHashFunction (cryptoInfo->pkcs5);
if (Randinit() != ERR_SUCCESS) 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); UserEnrichRandomPool (NULL);

View File

@@ -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 ); 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 FakeDosNameForDevice ( const char *lpszDiskFile , char *lpszDosDevice , size_t cbDosDevice, char *lpszCFDevice , size_t cbCFDevice, BOOL bNameOnly );
int RemoveFakeDosName ( char *lpszDiskFile , char *lpszDosDevice ); int RemoveFakeDosName ( char *lpszDiskFile , char *lpszDosDevice );
void AbortProcessDirect ( wchar_t *abortMsg );
void AbortProcess ( char *stringId ); void AbortProcess ( char *stringId );
void AbortProcessSilent ( void ); void AbortProcessSilent ( void );
void *err_malloc ( size_t size ); void *err_malloc ( size_t size );

View File

@@ -11,6 +11,7 @@
#include "Platform/PlatformBase.h" #include "Platform/PlatformBase.h"
#include "Dlgcode.h" #include "Dlgcode.h"
#include <strsafe.h>
namespace VeraCrypt namespace VeraCrypt
{ {
@@ -62,6 +63,38 @@ namespace VeraCrypt
const char *SrcPos; 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 struct TimeOut : public Exception
{ {
TimeOut (const char *srcPos) { } TimeOut (const char *srcPos) { }

View File

@@ -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="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="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_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_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="INIT_RICHEDIT">Error: Failed to load the Rich Edit system library.</string>
<string lang="en" key="INTRO_TITLE">VeraCrypt Volume Creation Wizard</string> <string lang="en" key="INTRO_TITLE">VeraCrypt Volume Creation Wizard</string>

View File

@@ -230,7 +230,13 @@ int ChangePwd (const char *lpszVolume, Password *oldPassword, int old_pkcs5, BOO
} }
if (Randinit ()) if (Randinit ())
{
if (CryptoAPILastError == ERROR_SUCCESS)
nStatus = ERR_RAND_INIT_FAILED;
else
nStatus = ERR_CAPI_INIT_FAILED;
goto error; goto error;
}
SetRandomPoolEnrichedByUserStatus (FALSE); /* force the display of the random enriching dialog */ SetRandomPoolEnrichedByUserStatus (FALSE); /* force the display of the random enriching dialog */

View File

@@ -60,12 +60,14 @@ HANDLE hNetAPI32 = NULL;
// CryptoAPI // CryptoAPI
BOOL CryptoAPIAvailable = FALSE; BOOL CryptoAPIAvailable = FALSE;
DWORD CryptoAPILastError = ERROR_SUCCESS;
HCRYPTPROV hCryptProv; HCRYPTPROV hCryptProv;
/* Init the random number generator, setup the hooks, and start the thread */ /* Init the random number generator, setup the hooks, and start the thread */
int Randinit () int Randinit ()
{ {
DWORD dwLastError = ERROR_SUCCESS;
if (GetMaxPkcs5OutSize() > RNG_POOL_SIZE) if (GetMaxPkcs5OutSize() > RNG_POOL_SIZE)
TC_THROW_FATAL_EXCEPTION; TC_THROW_FATAL_EXCEPTION;
@@ -75,6 +77,7 @@ int Randinit ()
InitializeCriticalSection (&critRandProt); InitializeCriticalSection (&critRandProt);
bRandDidInit = TRUE; bRandDidInit = TRUE;
CryptoAPILastError = ERROR_SUCCESS;
if (pRandPool == NULL) if (pRandPool == NULL)
{ {
@@ -99,9 +102,12 @@ int Randinit ()
goto error; goto error;
} }
if (!CryptAcquireContext (&hCryptProv, NULL, NULL, PROV_RSA_FULL, 0) if (!CryptAcquireContext (&hCryptProv, NULL, MS_ENHANCED_PROV, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT | CRYPT_SILENT))
&& !CryptAcquireContext (&hCryptProv, NULL, NULL, PROV_RSA_FULL, CRYPT_NEWKEYSET)) {
CryptoAPIAvailable = FALSE; CryptoAPIAvailable = FALSE;
CryptoAPILastError = GetLastError ();
goto error;
}
else else
CryptoAPIAvailable = TRUE; CryptoAPIAvailable = TRUE;
@@ -111,7 +117,9 @@ int Randinit ()
return 0; return 0;
error: error:
dwLastError = GetLastError();
RandStop (TRUE); RandStop (TRUE);
SetLastError (dwLastError);
return 1; return 1;
} }
@@ -149,6 +157,7 @@ void RandStop (BOOL freePool)
{ {
CryptReleaseContext (hCryptProv, 0); CryptReleaseContext (hCryptProv, 0);
CryptoAPIAvailable = FALSE; CryptoAPIAvailable = FALSE;
CryptoAPILastError = ERROR_SUCCESS;
} }
hMouse = NULL; hMouse = NULL;
@@ -359,13 +368,19 @@ BOOL RandgetBytesFull ( void* hwndDlg, unsigned char *buf , int len, BOOL forceS
if (bDidSlowPoll == FALSE || forceSlowPoll) if (bDidSlowPoll == FALSE || forceSlowPoll)
{ {
if (!SlowPoll ()) if (!SlowPoll ())
{
handleError ((HWND) hwndDlg, ERR_CAPI_INIT_FAILED);
ret = FALSE; ret = FALSE;
}
else else
bDidSlowPoll = TRUE; bDidSlowPoll = TRUE;
} }
if (!FastPoll ()) if (!FastPoll ())
{
handleError ((HWND) hwndDlg, ERR_CAPI_INIT_FAILED);
ret = FALSE; ret = FALSE;
}
/* There's never more than RNG_POOL_SIZE worth of randomess */ /* There's never more than RNG_POOL_SIZE worth of randomess */
if ( (!allowAnyLength) && (len > RNG_POOL_SIZE)) if ( (!allowAnyLength) && (len > RNG_POOL_SIZE))
@@ -692,13 +707,24 @@ BOOL SlowPoll (void)
CloseHandle (hDevice); CloseHandle (hDevice);
} }
// CryptoAPI // CryptoAPI: We always have a valid CryptoAPI context when we arrive here but
if (CryptoAPIAvailable && CryptGenRandom (hCryptProv, sizeof (buffer), buffer)) // we keep the check for clarity purpose
if ( !CryptoAPIAvailable )
return FALSE;
if (CryptGenRandom (hCryptProv, sizeof (buffer), buffer))
{
RandaddBuf (buffer, sizeof (buffer)); RandaddBuf (buffer, sizeof (buffer));
burn(buffer, sizeof (buffer)); burn(buffer, sizeof (buffer));
Randmix(); Randmix();
return TRUE; 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)); RandaddBuf ((unsigned char *) &dwTicks, sizeof (dwTicks));
} }
// CryptoAPI // CryptoAPI: We always have a valid CryptoAPI context when we arrive here but
if (CryptoAPIAvailable && CryptGenRandom (hCryptProv, sizeof (buffer), buffer)) // we keep the check for clarity purpose
if ( !CryptoAPIAvailable )
return FALSE;
if (CryptGenRandom (hCryptProv, sizeof (buffer), buffer))
{
RandaddBuf (buffer, sizeof (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 */ /* Apply the pool mixing function */
Randmix(); Randmix();

View File

@@ -58,6 +58,7 @@ BOOL RandgetBytesFull ( void* hwndDlg, unsigned char *buf , int len, BOOL forceS
extern BOOL volatile bFastPollEnabled; extern BOOL volatile bFastPollEnabled;
extern BOOL volatile bRandmixEnabled; extern BOOL volatile bRandmixEnabled;
extern DWORD CryptoAPILastError;
LRESULT CALLBACK MouseProc ( int nCode , WPARAM wParam , LPARAM lParam ); LRESULT CALLBACK MouseProc ( int nCode , WPARAM wParam , LPARAM lParam );
LRESULT CALLBACK KeyboardProc ( int nCode , WPARAM wParam , LPARAM lParam ); LRESULT CALLBACK KeyboardProc ( int nCode , WPARAM wParam , LPARAM lParam );

View File

@@ -301,7 +301,9 @@ enum
ERR_SYS_HIDVOL_HEAD_REENC_MODE_WRONG = 31, ERR_SYS_HIDVOL_HEAD_REENC_MODE_WRONG = 31,
ERR_NONSYS_INPLACE_ENC_INCOMPLETE = 32, ERR_NONSYS_INPLACE_ENC_INCOMPLETE = 32,
ERR_USER_ABORT = 33, 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 #endif // #ifndef TCDEFS_H

View File

@@ -476,7 +476,10 @@ void ExpandVolumeWizard (HWND hwndDlg, char *lpszVolume)
} }
if (Randinit() != ERR_SUCCESS) { 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; goto error;
} }

View File

@@ -602,7 +602,13 @@ static int ExpandVolume (HWND hwndDlg, char *lpszVolume, Password *pVolumePasswo
} }
if (Randinit ()) 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) if (!bDevice && bPreserveTimestamp)
{ {

View File

@@ -9000,7 +9000,15 @@ int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance, char *lpszComm
nPbar = IDC_PROGRESS_BAR; nPbar = IDC_PROGRESS_BAR;
if (Randinit ()) 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); RegisterRedTick(hInstance);

View File

@@ -8199,7 +8199,10 @@ noHidden:
if (Randinit() != ERR_SUCCESS) 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; goto error;
} }