From 77885de85e577275d2528e738914ba51b5def585 Mon Sep 17 00:00:00 2001 From: Mounir IDRASSI Date: Sun, 31 Jan 2016 20:28:00 +0100 Subject: Windows: Implement GUI indicator for entropy collected from mouse movements. --- src/Common/Common.rc | 30 +++--- src/Common/Dlgcode.c | 185 +++++++++++++++++++++++++++++------ src/Common/Language.xml | 1 + src/Common/Random.c | 14 ++- src/Common/Random.h | 3 +- src/Common/Resource.h | 6 +- src/ExpandVolume/DlgExpandVolume.cpp | 85 ++++++++++++++-- src/ExpandVolume/ExpandVolume.rc | 16 +-- src/Format/Format.rc | 4 + src/Format/Tcformat.c | Bin 636272 -> 645222 bytes 10 files changed, 284 insertions(+), 60 deletions(-) diff --git a/src/Common/Common.rc b/src/Common/Common.rc index 00f8d949..401e278d 100644 --- a/src/Common/Common.rc +++ b/src/Common/Common.rc @@ -204,7 +204,7 @@ BEGIN CONTROL "",IDC_INFO_BOX_TEXT,"RichEdit20W",ES_MULTILINE | ES_READONLY | ES_NUMBER | WS_BORDER | WS_VSCROLL | WS_TABSTOP,5,6,361,188 END -IDD_KEYFILE_GENERATOR DIALOGEX 0, 0, 357, 325 +IDD_KEYFILE_GENERATOR DIALOGEX 0, 0, 357, 362 STYLE DS_SETFONT | DS_MODALFRAME | DS_FIXEDSYS | DS_CENTER | WS_POPUP | WS_CAPTION | WS_SYSMENU CAPTION "VeraCrypt - Keyfile Generator" FONT 8, "MS Shell Dlg", 400, 0, 0x1 @@ -212,20 +212,22 @@ BEGIN DEFPUSHBUTTON "Close",IDCLOSE,291,10,59,14 COMBOBOX IDC_PRF_ID,97,49,91,90,CBS_DROPDOWNLIST | WS_TABSTOP CONTROL "Display pool content",IDC_DISPLAY_POOL_CONTENTS,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,209,51,141,10 - EDITTEXT IDC_NUMBER_KEYFILES,124,244,51,14,ES_RIGHT | ES_AUTOHSCROLL | ES_NUMBER - EDITTEXT IDC_KEYFILES_SIZE,124,264,51,14,ES_RIGHT | ES_AUTOHSCROLL | ES_NUMBER + EDITTEXT IDC_NUMBER_KEYFILES,124,278,51,14,ES_RIGHT | ES_AUTOHSCROLL | ES_NUMBER + EDITTEXT IDC_KEYFILES_SIZE,124,298,51,14,ES_RIGHT | ES_AUTOHSCROLL | ES_NUMBER CONTROL "Random size ( 64 <-> 1048576 )",IDC_KEYFILES_RANDOM_SIZE, - "Button",BS_AUTOCHECKBOX | WS_TABSTOP,181,266,174,10 - EDITTEXT IDC_KEYFILES_BASE_NAME,124,284,141,14,ES_AUTOHSCROLL - PUSHBUTTON "Generate and Save Keyfile...",IDC_GENERATE_AND_SAVE_KEYFILE,124,302,141,14 + "Button",BS_AUTOCHECKBOX | WS_TABSTOP,181,300,174,10 + EDITTEXT IDC_KEYFILES_BASE_NAME,124,318,141,14,ES_AUTOHSCROLL + PUSHBUTTON "Generate and Save Keyfile...",IDC_GENERATE_AND_SAVE_KEYFILE,124,336,141,14 LTEXT "IMPORTANT: Move your mouse as randomly as possible within this window. The longer you move it, the better. This significantly increases the cryptographic strength of the keyfile.",IDT_KEYFILE_GENERATOR_NOTE,11,5,271,33 CONTROL "",IDC_STATIC,"Static",SS_ETCHEDHORZ,1,40,356,1,WS_EX_STATICEDGE RTEXT "Mixing PRF:",IDT_PRF,7,51,85,10,SS_CENTERIMAGE GROUPBOX "Current Pool Content",IDT_POOL_CONTENTS,6,70,344,170 CONTROL "",IDC_POOL_CONTENTS,"Static",SS_LEFTNOWORDWRAP | WS_GROUP,16,83,323,148,WS_EX_TRANSPARENT - RTEXT "Number of keyfiles:",IDT_NUMBER_KEYFILES,9,247,110,8 - RTEXT "Keyfiles base name:",IDT_KEYFILES_BASE_NAME,9,287,110,8 - RTEXT "Keyfiles size (in Bytes):",IDT_KEYFILES_SIZE,9,266,110,8 + RTEXT "Number of keyfiles:",IDT_NUMBER_KEYFILES,9,281,110,8 + RTEXT "Keyfiles base name:",IDT_KEYFILES_BASE_NAME,9,321,110,8 + RTEXT "Keyfiles size (in Bytes):",IDT_KEYFILES_SIZE,9,300,110,8 + CONTROL "",IDC_ENTROPY_BAR,"msctls_progress32",PBS_SMOOTH | WS_BORDER,18,255,321,12 + GROUPBOX "Randomness Collected From Mouse Movements",IDT_ENTROPY_BAR,6,244,344,29 END IDD_MULTI_CHOICE_DLG DIALOGEX 0, 0, 167, 322 @@ -293,12 +295,12 @@ BEGIN GROUPBOX "",IDC_STATIC,5,2,228,51 END -IDD_RANDOM_POOL_ENRICHMENT DIALOGEX 0, 0, 308, 270 +IDD_RANDOM_POOL_ENRICHMENT DIALOGEX 0, 0, 308, 301 STYLE DS_SETFONT | DS_MODALFRAME | DS_FIXEDSYS | DS_CENTER | WS_POPUP | WS_CAPTION | WS_SYSMENU CAPTION "VeraCrypt - Random Pool Enrichment" FONT 8, "MS Shell Dlg", 400, 0, 0x1 BEGIN - DEFPUSHBUTTON "&Continue",IDC_CONTINUE,119,248,71,14 + DEFPUSHBUTTON "&Continue",IDC_CONTINUE,119,278,71,14 COMBOBOX IDC_PRF_ID,79,49,91,90,CBS_DROPDOWNLIST | WS_TABSTOP LTEXT "IMPORTANT: Move your mouse as randomly as possible within this window. The longer you move it, the better. This significantly increases security. When done, click 'Continue'.",IDT_RANDOM_POOL_ENRICHMENT_NOTE,11,6,282,25 CONTROL "",IDC_STATIC,"Static",SS_ETCHEDHORZ,1,37,307,1,WS_EX_STATICEDGE @@ -306,6 +308,8 @@ BEGIN GROUPBOX "Current Pool Content",IDT_POOL_CONTENTS,6,70,296,170 CONTROL "",IDC_POOL_CONTENTS,"Static",SS_LEFTNOWORDWRAP | WS_GROUP,16,83,282,148,WS_EX_TRANSPARENT CONTROL "Display pool content",IDC_DISPLAY_POOL_CONTENTS,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,191,51,111,10 + CONTROL "",IDC_ENTROPY_BAR,"msctls_progress32",PBS_SMOOTH | WS_BORDER,16,255,275,12 + GROUPBOX "Randomness Collected From Mouse Movements",IDT_ENTROPY_BAR,7,244,294,29 END IDD_STATIC_MODELESS_WAIT_DLG DIALOGEX 0, 0, 292, 42 @@ -403,7 +407,7 @@ BEGIN BEGIN LEFTMARGIN, 7 TOPMARGIN, 7 - BOTTOMMARGIN, 321 + BOTTOMMARGIN, 358 END IDD_MULTI_CHOICE_DLG, DIALOG @@ -451,7 +455,7 @@ BEGIN LEFTMARGIN, 7 RIGHTMARGIN, 301 TOPMARGIN, 7 - BOTTOMMARGIN, 267 + BOTTOMMARGIN, 298 END IDD_STATIC_MODELESS_WAIT_DLG, DIALOG diff --git a/src/Common/Dlgcode.c b/src/Common/Dlgcode.c index 0d3db770..e2b00f7a 100644 --- a/src/Common/Dlgcode.c +++ b/src/Common/Dlgcode.c @@ -5350,8 +5350,15 @@ static BOOL CALLBACK RandomPoolEnrichementDlgProc (HWND hwndDlg, UINT msg, WPARA WORD hw = HIWORD (wParam); static unsigned char randPool [RNG_POOL_SIZE]; static unsigned char lastRandPool [RNG_POOL_SIZE]; + static unsigned char maskRandPool [RNG_POOL_SIZE]; + static BOOL bUseMask = FALSE; + static DWORD mouseEntropyGathered = 0xFFFFFFFF; + static DWORD mouseEventsInitialCount = 0; + /* max value of entropy needed to fill all random pool = 8 * RNG_POOL_SIZE = 2560 bits */ + static const DWORD maxEntropyLevel = RNG_POOL_SIZE * 8; + static HWND hEntropyBar = NULL; static wchar_t outputDispBuffer [RNG_POOL_SIZE * 3 + RANDPOOL_DISPLAY_ROWS + 2]; - static BOOL bDisplayPoolContents = TRUE; + static BOOL bDisplayPoolContents = FALSE; static BOOL bRandPoolDispAscii = FALSE; int hash_algo = RandGetHashFunction(); int hid; @@ -5361,10 +5368,24 @@ static BOOL CALLBACK RandomPoolEnrichementDlgProc (HWND hwndDlg, UINT msg, WPARA case WM_INITDIALOG: { HWND hComboBox = GetDlgItem (hwndDlg, IDC_PRF_ID); + HCRYPTPROV hRngProv = NULL; VirtualLock (randPool, sizeof(randPool)); VirtualLock (lastRandPool, sizeof(lastRandPool)); VirtualLock (outputDispBuffer, sizeof(outputDispBuffer)); + VirtualLock (&mouseEntropyGathered, sizeof(mouseEntropyGathered)); + VirtualLock (&mouseEventsInitialCount, sizeof(mouseEventsInitialCount)); + VirtualLock (maskRandPool, sizeof(maskRandPool)); + + mouseEntropyGathered = 0xFFFFFFFF; + mouseEventsInitialCount = 0; + bUseMask = FALSE; + if (CryptAcquireContext (&hRngProv, NULL, MS_ENHANCED_PROV, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT | CRYPT_SILENT)) + { + if (CryptGenRandom (hRngProv, sizeof (maskRandPool), maskRandPool)) + bUseMask = TRUE; + CryptReleaseContext (hRngProv, 0); + } LocalizeDialog (hwndDlg, "IDD_RANDOM_POOL_ENRICHMENT"); @@ -5380,6 +5401,10 @@ static BOOL CALLBACK RandomPoolEnrichementDlgProc (HWND hwndDlg, UINT msg, WPARA SetTimer (hwndDlg, 0xfd, RANDPOOL_DISPLAY_REFRESH_INTERVAL, NULL); SendMessage (GetDlgItem (hwndDlg, IDC_POOL_CONTENTS), WM_SETFONT, (WPARAM) hFixedDigitFont, (LPARAM) TRUE); + + hEntropyBar = GetDlgItem (hwndDlg, IDC_ENTROPY_BAR); + SendMessage (hEntropyBar, PBM_SETRANGE32, 0, maxEntropyLevel); + SendMessage (hEntropyBar, PBM_SETSTEP, 1, 0); return 1; } @@ -5388,30 +5413,67 @@ static BOOL CALLBACK RandomPoolEnrichementDlgProc (HWND hwndDlg, UINT msg, WPARA wchar_t tmp[4]; unsigned char tmpByte; int col, row; + DWORD mouseEventsCounter; - if (bDisplayPoolContents) + RandpeekBytes (hwndDlg, randPool, sizeof (randPool), &mouseEventsCounter); + + /* conservative estimate: 1 mouse move event brings 1 bit of entropy + * https://security.stackexchange.com/questions/32844/for-how-much-time-should-i-randomly-move-the-mouse-for-generating-encryption-key/32848#32848 + */ + if (mouseEntropyGathered == 0xFFFFFFFF) { - RandpeekBytes (hwndDlg, randPool, sizeof (randPool)); + mouseEventsInitialCount = mouseEventsCounter; + mouseEntropyGathered = 0; + } + else + { + if ( mouseEntropyGathered < maxEntropyLevel + && (mouseEventsCounter >= mouseEventsInitialCount) + && (mouseEventsCounter - mouseEventsInitialCount) <= maxEntropyLevel) + mouseEntropyGathered = mouseEventsCounter - mouseEventsInitialCount; + else + mouseEntropyGathered = maxEntropyLevel; - if (memcmp (lastRandPool, randPool, sizeof(lastRandPool)) != 0) - { - outputDispBuffer[0] = 0; + SendMessage (hEntropyBar, PBM_SETPOS, + (WPARAM) (mouseEntropyGathered), + 0); + } + + if (memcmp (lastRandPool, randPool, sizeof(lastRandPool)) != 0) + { + outputDispBuffer[0] = 0; - for (row = 0; row < RANDPOOL_DISPLAY_ROWS; row++) + for (row = 0; row < RANDPOOL_DISPLAY_ROWS; row++) + { + for (col = 0; col < RANDPOOL_DISPLAY_COLUMNS; col++) { - for (col = 0; col < RANDPOOL_DISPLAY_COLUMNS; col++) + if (bDisplayPoolContents) { tmpByte = randPool[row * RANDPOOL_DISPLAY_COLUMNS + col]; - StringCbPrintfW (tmp, sizeof(tmp), bRandPoolDispAscii ? ((tmpByte >= 32 && tmpByte < 255 && tmpByte != L'&') ? L" %c " : L" . ") : L"%02X ", tmpByte); - StringCbCatW (outputDispBuffer, sizeof(outputDispBuffer), tmp); } - StringCbCatW (outputDispBuffer, sizeof(outputDispBuffer), L"\n"); - } - SetWindowText (GetDlgItem (hwndDlg, IDC_POOL_CONTENTS), outputDispBuffer); + else if (bUseMask) + { + /* use mask to compute a randomized ascii representation */ + tmpByte = (randPool[row * RANDPOOL_DISPLAY_COLUMNS + col] - + lastRandPool[row * RANDPOOL_DISPLAY_COLUMNS + col]) ^ maskRandPool [row * RANDPOOL_DISPLAY_COLUMNS + col]; + tmp[0] = (wchar_t) (((tmpByte >> 4) % 6) + L'*'); + tmp[1] = (wchar_t) (((tmpByte & 0x0F) % 6) + L'*'); + tmp[2] = L' '; + tmp[3] = 0; + } + else + { + StringCbCopyW (tmp, sizeof(tmp), L"** "); + } - memcpy (lastRandPool, randPool, sizeof(lastRandPool)); + StringCbCatW (outputDispBuffer, sizeof(outputDispBuffer), tmp); + } + StringCbCatW (outputDispBuffer, sizeof(outputDispBuffer), L"\n"); } + SetWindowText (GetDlgItem (hwndDlg, IDC_POOL_CONTENTS), outputDispBuffer); + + memcpy (lastRandPool, randPool, sizeof(lastRandPool)); } return 1; } @@ -5458,6 +5520,9 @@ exit: burn (randPool, sizeof(randPool)); burn (lastRandPool, sizeof(lastRandPool)); burn (outputDispBuffer, sizeof(outputDispBuffer)); + burn (&mouseEntropyGathered, sizeof(mouseEntropyGathered)); + burn (&mouseEventsInitialCount, sizeof(mouseEventsInitialCount)); + burn (maskRandPool, sizeof(maskRandPool)); // Attempt to wipe the pool contents in the GUI text area wmemset (tmp, L' ', RNG_POOL_SIZE); @@ -5498,8 +5563,15 @@ BOOL CALLBACK KeyfileGeneratorDlgProc (HWND hwndDlg, UINT msg, WPARAM wParam, LP WORD hw = HIWORD (wParam); static unsigned char randPool [RNG_POOL_SIZE]; static unsigned char lastRandPool [RNG_POOL_SIZE]; + static unsigned char maskRandPool [RNG_POOL_SIZE]; + static BOOL bUseMask = FALSE; + static DWORD mouseEntropyGathered = 0xFFFFFFFF; + static DWORD mouseEventsInitialCount = 0; + /* max value of entropy needed to fill all random pool = 8 * RNG_POOL_SIZE = 2560 bits */ + static const DWORD maxEntropyLevel = RNG_POOL_SIZE * 8; + static HWND hEntropyBar = NULL; static wchar_t outputDispBuffer [RNG_POOL_SIZE * 3 + RANDPOOL_DISPLAY_ROWS + 2]; - static BOOL bDisplayPoolContents = TRUE; + static BOOL bDisplayPoolContents = FALSE; static BOOL bRandPoolDispAscii = FALSE; int hash_algo = RandGetHashFunction(); int hid; @@ -5509,10 +5581,24 @@ BOOL CALLBACK KeyfileGeneratorDlgProc (HWND hwndDlg, UINT msg, WPARAM wParam, LP case WM_INITDIALOG: { HWND hComboBox = GetDlgItem (hwndDlg, IDC_PRF_ID); + HCRYPTPROV hRngProv = NULL; VirtualLock (randPool, sizeof(randPool)); VirtualLock (lastRandPool, sizeof(lastRandPool)); VirtualLock (outputDispBuffer, sizeof(outputDispBuffer)); + VirtualLock (&mouseEntropyGathered, sizeof(mouseEntropyGathered)); + VirtualLock (&mouseEventsInitialCount, sizeof(mouseEventsInitialCount)); + VirtualLock (maskRandPool, sizeof(maskRandPool)); + + mouseEntropyGathered = 0xFFFFFFFF; + mouseEventsInitialCount = 0; + bUseMask = FALSE; + if (CryptAcquireContext (&hRngProv, NULL, MS_ENHANCED_PROV, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT | CRYPT_SILENT)) + { + if (CryptGenRandom (hRngProv, sizeof (maskRandPool), maskRandPool)) + bUseMask = TRUE; + CryptReleaseContext (hRngProv, 0); + } LocalizeDialog (hwndDlg, "IDD_KEYFILE_GENERATOR"); @@ -5525,6 +5611,9 @@ BOOL CALLBACK KeyfileGeneratorDlgProc (HWND hwndDlg, UINT msg, WPARAM wParam, LP SelectAlgo (hComboBox, &hash_algo); SetCheckBox (hwndDlg, IDC_DISPLAY_POOL_CONTENTS, bDisplayPoolContents); + hEntropyBar = GetDlgItem (hwndDlg, IDC_ENTROPY_BAR); + SendMessage (hEntropyBar, PBM_SETRANGE32, 0, maxEntropyLevel); + SendMessage (hEntropyBar, PBM_SETSTEP, 1, 0); #ifndef VOLFORMAT if (Randinit ()) @@ -5551,30 +5640,67 @@ BOOL CALLBACK KeyfileGeneratorDlgProc (HWND hwndDlg, UINT msg, WPARAM wParam, LP wchar_t tmp[4]; unsigned char tmpByte; int col, row; + DWORD mouseEventsCounter; + + RandpeekBytes (hwndDlg, randPool, sizeof (randPool), &mouseEventsCounter); - if (bDisplayPoolContents) + /* conservative estimate: 1 mouse move event brings 1 bit of entropy + * https://security.stackexchange.com/questions/32844/for-how-much-time-should-i-randomly-move-the-mouse-for-generating-encryption-key/32848#32848 + */ + if (mouseEntropyGathered == 0xFFFFFFFF) + { + mouseEventsInitialCount = mouseEventsCounter; + mouseEntropyGathered = 0; + } + else { - RandpeekBytes (hwndDlg, randPool, sizeof (randPool)); + if ( mouseEntropyGathered < maxEntropyLevel + && (mouseEventsCounter >= mouseEventsInitialCount) + && (mouseEventsCounter - mouseEventsInitialCount) <= maxEntropyLevel) + mouseEntropyGathered = mouseEventsCounter - mouseEventsInitialCount; + else + mouseEntropyGathered = maxEntropyLevel; - if (memcmp (lastRandPool, randPool, sizeof(lastRandPool)) != 0) - { - outputDispBuffer[0] = 0; + SendMessage (hEntropyBar, PBM_SETPOS, + (WPARAM) (mouseEntropyGathered), + 0); + } + + if (memcmp (lastRandPool, randPool, sizeof(lastRandPool)) != 0) + { + outputDispBuffer[0] = 0; - for (row = 0; row < RANDPOOL_DISPLAY_ROWS; row++) + for (row = 0; row < RANDPOOL_DISPLAY_ROWS; row++) + { + for (col = 0; col < RANDPOOL_DISPLAY_COLUMNS; col++) { - for (col = 0; col < RANDPOOL_DISPLAY_COLUMNS; col++) + if (bDisplayPoolContents) { tmpByte = randPool[row * RANDPOOL_DISPLAY_COLUMNS + col]; - StringCbPrintfW (tmp, sizeof(tmp), bRandPoolDispAscii ? ((tmpByte >= 32 && tmpByte < 255 && tmpByte != L'&') ? L" %c " : L" . ") : L"%02X ", tmpByte); - StringCbCatW (outputDispBuffer, sizeof(outputDispBuffer), tmp); } - StringCbCatW (outputDispBuffer, sizeof(outputDispBuffer), L"\n"); - } - SetWindowText (GetDlgItem (hwndDlg, IDC_POOL_CONTENTS), outputDispBuffer); + else if (bUseMask) + { + /* use mask to compute a randomized ASCII representation */ + tmpByte = (randPool[row * RANDPOOL_DISPLAY_COLUMNS + col] - + lastRandPool[row * RANDPOOL_DISPLAY_COLUMNS + col]) ^ maskRandPool [row * RANDPOOL_DISPLAY_COLUMNS + col]; + tmp[0] = (wchar_t) (((tmpByte >> 4) % 6) + L'*'); + tmp[1] = (wchar_t) (((tmpByte & 0x0F) % 6) + L'*'); + tmp[2] = L' '; + tmp[3] = 0; + } + else + { + StringCbCopyW (tmp, sizeof(tmp), L"** "); + } - memcpy (lastRandPool, randPool, sizeof(lastRandPool)); + StringCbCatW (outputDispBuffer, sizeof(outputDispBuffer), tmp); + } + StringCbCatW (outputDispBuffer, sizeof(outputDispBuffer), L"\n"); } + SetWindowText (GetDlgItem (hwndDlg, IDC_POOL_CONTENTS), outputDispBuffer); + + memcpy (lastRandPool, randPool, sizeof(lastRandPool)); } return 1; } @@ -5797,6 +5923,9 @@ exit: burn (randPool, sizeof(randPool)); burn (lastRandPool, sizeof(lastRandPool)); burn (outputDispBuffer, sizeof(outputDispBuffer)); + burn (&mouseEntropyGathered, sizeof(mouseEntropyGathered)); + burn (&mouseEventsInitialCount, sizeof(mouseEventsInitialCount)); + burn (maskRandPool, sizeof(maskRandPool)); // Attempt to wipe the pool contents in the GUI text area wmemset (tmp, L' ', RNG_POOL_SIZE); diff --git a/src/Common/Language.xml b/src/Common/Language.xml index a89b2c8c..d994bf63 100644 --- a/src/Common/Language.xml +++ b/src/Common/Language.xml @@ -1387,6 +1387,7 @@ The entered password contains Unicode characters that couldn't be converted to UTF-8 representation. 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 diff --git a/src/Common/Random.c b/src/Common/Random.c index f6820c91..31dea511 100644 --- a/src/Common/Random.c +++ b/src/Common/Random.c @@ -74,6 +74,7 @@ void RandAddInt64 (unsigned __int64 x) HHOOK hMouse = NULL; /* Mouse hook for the random number generator */ HHOOK hKeyboard = NULL; /* Keyboard hook for the random number generator */ +DWORD ProcessedMouseEventsCounter = 0; /* Variables for thread control, the thread is used to gather up info about the system in in the background */ @@ -103,6 +104,7 @@ int Randinit () bRandDidInit = TRUE; CryptoAPILastError = ERROR_SUCCESS; + ProcessedMouseEventsCounter = 0; if (pRandPool == NULL) { @@ -351,7 +353,7 @@ void RandaddBuf (void *buf, int len) } } -BOOL RandpeekBytes (void* hwndDlg, unsigned char *buf, int len) +BOOL RandpeekBytes (void* hwndDlg, unsigned char *buf, int len, DWORD* mouseCounter) { if (!bRandDidInit) return FALSE; @@ -363,6 +365,7 @@ BOOL RandpeekBytes (void* hwndDlg, unsigned char *buf, int len) } EnterCriticalSection (&critRandProt); + *mouseCounter = ProcessedMouseEventsCounter; memcpy (buf, pRandPool, len); LeaveCriticalSection (&critRandProt); @@ -476,6 +479,7 @@ LRESULT CALLBACK MouseProc (int nCode, WPARAM wParam, LPARAM lParam) { static DWORD dwLastTimer; static unsigned __int32 lastCrc, lastCrc2; + static POINT lastPoint; MOUSEHOOKSTRUCT *lpMouse = (MOUSEHOOKSTRUCT *) lParam; if (nCode < 0) @@ -486,6 +490,7 @@ LRESULT CALLBACK MouseProc (int nCode, WPARAM wParam, LPARAM lParam) DWORD j = dwLastTimer - dwTimer; unsigned __int32 crc = 0L; int i; + POINT pt = lpMouse->pt; dwLastTimer = dwTimer; @@ -509,6 +514,13 @@ LRESULT CALLBACK MouseProc (int nCode, WPARAM wParam, LPARAM lParam) } EnterCriticalSection (&critRandProt); + /* only count real mouse messages in entropy estimation */ + if ( (nCode == HC_ACTION) && (wParam == WM_MOUSEMOVE) + && ((pt.x != lastPoint.x) || (pt.y != lastPoint.y))) + { + ProcessedMouseEventsCounter++; + lastPoint = pt; + } RandaddInt32 ((unsigned __int32) (crc + timeCrc)); LeaveCriticalSection (&critRandProt); } diff --git a/src/Common/Random.h b/src/Common/Random.h index 4f09a5f5..ef8ee79e 100644 --- a/src/Common/Random.h +++ b/src/Common/Random.h @@ -45,7 +45,7 @@ BOOL Randmix ( void ); void RandaddBuf ( void *buf , int len ); BOOL FastPoll ( void ); BOOL SlowPoll ( void ); -BOOL RandpeekBytes ( void* hwndDlg, unsigned char *buf , int len ); +BOOL RandpeekBytes ( void* hwndDlg, unsigned char *buf , int len, DWORD* mouseCounter ); /* Get len random bytes from the pool (max. RNG_POOL_SIZE bytes per a single call) */ BOOL RandgetBytes ( void* hwndDlg, unsigned char *buf , int len, BOOL forceSlowPoll ); @@ -61,6 +61,7 @@ BOOL RandgetBytesFull ( void* hwndDlg, unsigned char *buf , int len, BOOL forceS extern BOOL volatile bFastPollEnabled; extern BOOL volatile bRandmixEnabled; extern DWORD CryptoAPILastError; +extern DWORD ProcessedMouseEventsCounter; void RandAddInt64 ( unsigned __int64 x ); diff --git a/src/Common/Resource.h b/src/Common/Resource.h index 0c536eb8..8755f6c3 100644 --- a/src/Common/Resource.h +++ b/src/Common/Resource.h @@ -195,15 +195,17 @@ #define IDC_VOLUME_LABEL 5133 #define IDT_VOLUME_LABEL 5134 #define IDC_KEYFILES_TRY_EMPTY_PASSWORD 5135 +#define IDC_ENTROPY_BAR 5136 +#define IDT_ENTROPY_BAR 5137 // Next default values for new objects // #ifdef APSTUDIO_INVOKED #ifndef APSTUDIO_READONLY_SYMBOLS #define _APS_NO_MFC 1 -#define _APS_NEXT_RESOURCE_VALUE 542 +#define _APS_NEXT_RESOURCE_VALUE 558 #define _APS_NEXT_COMMAND_VALUE 40001 -#define _APS_NEXT_CONTROL_VALUE 5136 +#define _APS_NEXT_CONTROL_VALUE 5138 #define _APS_NEXT_SYMED_VALUE 101 #endif #endif diff --git a/src/ExpandVolume/DlgExpandVolume.cpp b/src/ExpandVolume/DlgExpandVolume.cpp index a54252cd..135f8d48 100644 --- a/src/ExpandVolume/DlgExpandVolume.cpp +++ b/src/ExpandVolume/DlgExpandVolume.cpp @@ -240,6 +240,14 @@ BOOL CALLBACK ExpandVolProgressDlgProc (HWND hwndDlg, UINT msg, WPARAM wParam, L static EXPAND_VOL_THREAD_PARAMS *pProgressDlgParam; static BOOL bVolTransformStarted = FALSE; static BOOL showRandPool = TRUE; + static unsigned char randPool[16]; + static unsigned char maskRandPool [16]; + static BOOL bUseMask = FALSE; + static DWORD mouseEntropyGathered = 0xFFFFFFFF; + static DWORD mouseEventsInitialCount = 0; + /* max value of entropy needed to fill all random pool = 8 * RNG_POOL_SIZE = 2560 bits */ + static const DWORD maxEntropyLevel = RNG_POOL_SIZE * 8; + static HWND hEntropyBar = NULL; WORD lw = LOWORD (wParam); @@ -248,14 +256,29 @@ BOOL CALLBACK ExpandVolProgressDlgProc (HWND hwndDlg, UINT msg, WPARAM wParam, L case WM_INITDIALOG: { wchar_t szOldHostSize[512], szNewHostSize[512]; + HCRYPTPROV hRngProv; pProgressDlgParam = (EXPAND_VOL_THREAD_PARAMS*)lParam; bVolTransformStarted = FALSE; - showRandPool = TRUE; + showRandPool = FALSE; hCurPage = hwndDlg; nPbar = IDC_PROGRESS_BAR; + VirtualLock (randPool, sizeof(randPool)); + VirtualLock (&mouseEntropyGathered, sizeof(mouseEntropyGathered)); + VirtualLock (maskRandPool, sizeof(maskRandPool)); + + mouseEntropyGathered = 0xFFFFFFFF; + mouseEventsInitialCount = 0; + bUseMask = FALSE; + if (CryptAcquireContext (&hRngProv, NULL, MS_ENHANCED_PROV, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT | CRYPT_SILENT)) + { + if (CryptGenRandom (hRngProv, sizeof (maskRandPool), maskRandPool)) + bUseMask = TRUE; + CryptReleaseContext (hRngProv, 0); + } + GetSpaceString(szOldHostSize,sizeof(szOldHostSize),pProgressDlgParam->oldSize,pProgressDlgParam->bIsDevice); GetSpaceString(szNewHostSize,sizeof(szNewHostSize),pProgressDlgParam->newSize,pProgressDlgParam->bIsDevice); @@ -283,6 +306,9 @@ BOOL CALLBACK ExpandVolProgressDlgProc (HWND hwndDlg, UINT msg, WPARAM wParam, L } SendMessage (GetDlgItem (hwndDlg, IDC_DISPLAY_POOL_CONTENTS), BM_SETCHECK, showRandPool ? BST_CHECKED : BST_UNCHECKED, 0); + hEntropyBar = GetDlgItem (hwndDlg, IDC_ENTROPY_BAR); + SendMessage (hEntropyBar, PBM_SETRANGE32, 0, maxEntropyLevel); + SendMessage (hEntropyBar, PBM_SETSTEP, 1, 0); SetTimer (hwndDlg, TIMER_ID_RANDVIEW, TIMER_INTERVAL_RANDVIEW, NULL); } return 0; @@ -315,20 +341,56 @@ BOOL CALLBACK ExpandVolProgressDlgProc (HWND hwndDlg, UINT msg, WPARAM wParam, L { case TIMER_ID_RANDVIEW: { - unsigned char tmp[16] = {0}; wchar_t szRndPool[64] = {0}; + DWORD mouseEventsCounter; - if (!showRandPool) - return 1; + RandpeekBytes (hwndDlg, randPool, sizeof (randPool),&mouseEventsCounter); - RandpeekBytes (hwndDlg, tmp, sizeof (tmp)); + /* conservative estimate: 1 mouse move event brings 1 bit of entropy + * https://security.stackexchange.com/questions/32844/for-how-much-time-should-i-randomly-move-the-mouse-for-generating-encryption-key/32848#32848 + */ + if (mouseEntropyGathered == 0xFFFFFFFF) + { + mouseEventsInitialCount = mouseEventsCounter; + mouseEntropyGathered = 0; + } + else + { + if ( mouseEntropyGathered < maxEntropyLevel + && (mouseEventsCounter >= mouseEventsInitialCount) + && (mouseEventsCounter - mouseEventsInitialCount) <= maxEntropyLevel) + mouseEntropyGathered = mouseEventsCounter - mouseEventsInitialCount; + else + mouseEntropyGathered = maxEntropyLevel; + + SendMessage (hEntropyBar, PBM_SETPOS, + (WPARAM) (mouseEntropyGathered), + 0); + } - StringCbPrintfW (szRndPool, sizeof(szRndPool), L"%08X%08X%08X%08X", - *((DWORD*) (tmp + 12)), *((DWORD*) (tmp + 8)), *((DWORD*) (tmp + 4)), *((DWORD*) (tmp))); + if (showRandPool) + StringCbPrintfW (szRndPool, sizeof(szRndPool), L"%08X%08X%08X%08X", + *((DWORD*) (randPool + 12)), *((DWORD*) (randPool + 8)), *((DWORD*) (randPool + 4)), *((DWORD*) (randPool))); + else if (bUseMask) + { + for (int i = 0; i < 16; i++) + { + wchar_t tmp2[3]; + unsigned char tmpByte = randPool[i] ^ maskRandPool[i]; + tmp2[0] = (wchar_t) (((tmpByte >> 4) % 6) + L'*'); + tmp2[1] = (wchar_t) (((tmpByte & 0x0F) % 6) + L'*'); + tmp2[2] = 0; + StringCbCatW (szRndPool, sizeof(szRndPool), tmp2); + } + } + else + { + wmemset (szRndPool, L'*', 32); + } SetWindowText (GetDlgItem (hwndDlg, IDC_RANDOM_BYTES), szRndPool); - burn (tmp, sizeof(tmp)); + burn (randPool, sizeof(randPool)); burn (szRndPool, sizeof(szRndPool)); } return 1; @@ -382,6 +444,13 @@ BOOL CALLBACK ExpandVolProgressDlgProc (HWND hwndDlg, UINT msg, WPARAM wParam, L } return 0; + + case WM_NCDESTROY: + burn (randPool, sizeof (randPool)); + burn (&mouseEventsInitialCount, sizeof(mouseEventsInitialCount)); + burn (&mouseEntropyGathered, sizeof(mouseEntropyGathered)); + burn (maskRandPool, sizeof(maskRandPool)); + return 0; } return 0; diff --git a/src/ExpandVolume/ExpandVolume.rc b/src/ExpandVolume/ExpandVolume.rc index bf285001..41eb1642 100644 --- a/src/ExpandVolume/ExpandVolume.rc +++ b/src/ExpandVolume/ExpandVolume.rc @@ -100,7 +100,7 @@ BEGIN LTEXT "(Empty or 0 for default iterations)",IDC_PIM_HELP,115,46,189,8,NOT WS_VISIBLE END -IDD_EXPAND_PROGRESS_DLG DIALOGEX 0, 0, 376, 271 +IDD_EXPAND_PROGRESS_DLG DIALOGEX 0, 0, 376, 283 STYLE DS_SETFONT | DS_MODALFRAME | DS_FIXEDSYS | WS_POPUP | WS_CAPTION | WS_SYSMENU CAPTION "VeraCrypt Expander" FONT 8, "MS Shell Dlg", 0, 0, 0x0 @@ -120,16 +120,18 @@ BEGIN RTEXT "Volume: ",IDT_VOL_NAME,31,16,42,8 GROUPBOX "",IDC_STATIC,15,7,346,72 CONTROL "",IDC_EXPAND_VOLUME_NAME,"Static",SS_SIMPLE | WS_GROUP,80,16,275,8,WS_EX_TRANSPARENT - DEFPUSHBUTTON "Continue",IDOK,15,238,84,18 - PUSHBUTTON "Cancel",IDCANCEL,277,238,84,18 - EDITTEXT IDC_BOX_STATUS,15,162,346,66,ES_MULTILINE | ES_AUTOVSCROLL | ES_READONLY | ES_WANTRETURN | WS_VSCROLL + DEFPUSHBUTTON "Continue",IDOK,15,247,84,18 + PUSHBUTTON "Cancel",IDCANCEL,277,247,84,18 + EDITTEXT IDC_BOX_STATUS,15,176,346,66,ES_MULTILINE | ES_AUTOVSCROLL | ES_READONLY | ES_WANTRETURN | WS_VSCROLL CONTROL "",IDC_EXPAND_VOLUME_INITSPACE,"Static",SS_SIMPLE | WS_GROUP,80,64,275,8,WS_EX_TRANSPARENT RTEXT "Fill new space: ",IDT_INIT_SPACE,20,64,53,8 RTEXT "File system: ",IDT_FILE_SYS,31,28,42,8 CONTROL "",IDC_EXPAND_FILE_SYSTEM,"Static",SS_SIMPLE | WS_GROUP,80,28,275,8,WS_EX_TRANSPARENT RTEXT "Random Pool: ",IDT_RANDOM_POOL2,20,144,53,8 CONTROL "",IDC_RANDOM_BYTES,"Static",SS_SIMPLE | WS_GROUP,80,144,149,8,WS_EX_TRANSPARENT - CONTROL "",IDC_DISPLAY_POOL_CONTENTS,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,236,142,14,12 + CONTROL "Display pool content",IDC_DISPLAY_POOL_CONTENTS,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,236,142,125,12 + GROUPBOX "Randomness Collected From Mouse Movements",IDT_ENTROPY_BAR,20,156,214,18 + CONTROL "",IDC_ENTROPY_BAR,"msctls_progress32",WS_BORDER,31,165,193,6 END @@ -170,8 +172,8 @@ BEGIN VERTGUIDE, 80 VERTGUIDE, 355 TOPMARGIN, 9 - BOTTOMMARGIN, 256 - HORZGUIDE, 162 + BOTTOMMARGIN, 268 + HORZGUIDE, 176 END END #endif // APSTUDIO_INVOKED diff --git a/src/Format/Format.rc b/src/Format/Format.rc index 9c4c9a8c..0d1d8007 100644 --- a/src/Format/Format.rc +++ b/src/Format/Format.rc @@ -176,6 +176,8 @@ BEGIN RTEXT "Random Pool: ",IDT_RANDOM_POOL,2,39,54,8 GROUPBOX "",IDC_STATIC,0,32,225,35 CONTROL "",IDC_RANDOM_BYTES,"Static",SS_SIMPLE | WS_GROUP,57,38,155,8,WS_EX_TRANSPARENT + GROUPBOX "Randomness Collected From Mouse Movements",IDT_ENTROPY_BAR,0,153,224,18 + CONTROL "",IDC_ENTROPY_BAR,"msctls_progress32",WS_BORDER,11,162,202,6 END IDD_INTRO_PAGE_DLG DIALOGEX 0, 0, 226, 172 @@ -277,6 +279,8 @@ BEGIN CONTROL "",IDC_SYS_POOL_CONTENTS,"Static",SS_LEFTNOWORDWRAP | WS_GROUP,8,14,205,72,WS_EX_TRANSPARENT LTEXT "IMPORTANT: Move your mouse as randomly as possible within this window. The longer you move it, the better. This significantly increases the cryptographic strength of the encryption keys. Then click Next to continue.",IDT_COLLECTING_RANDOM_DATA_NOTE,1,112,224,40 GROUPBOX "Current pool content (partial)",IDT_PARTIAL_POOL_CONTENTS,0,5,222,88 + GROUPBOX "Randomness Collected From Mouse Movements",IDT_ENTROPY_BAR,0,154,224,18 + CONTROL "",IDC_ENTROPY_BAR,"msctls_progress32",WS_BORDER,11,163,202,6 END IDD_SYSENC_MULTI_BOOT_MODE_PAGE_DLG DIALOGEX 0, 0, 226, 172 diff --git a/src/Format/Tcformat.c b/src/Format/Tcformat.c index a159ca73..4a02ef6b 100644 Binary files a/src/Format/Tcformat.c and b/src/Format/Tcformat.c differ -- cgit v1.2.3