From 078614fbce14aaf820e8ce6389a1c95df30c6542 Mon Sep 17 00:00:00 2001 From: Mounir IDRASSI Date: Sun, 7 Dec 2014 11:23:18 +0100 Subject: Windows: Implement creation of multiple keyfiles at once. --- src/Common/Common.rc | 28 ++++---- src/Common/Dlgcode.c | 186 +++++++++++++++++++++++++++++++++++++++++++----- src/Common/Language.xml | 11 ++- src/Common/Resource.h | 24 ++++--- 4 files changed, 206 insertions(+), 43 deletions(-) diff --git a/src/Common/Common.rc b/src/Common/Common.rc index 5eff1b4d..29d35d23 100644 --- a/src/Common/Common.rc +++ b/src/Common/Common.rc @@ -194,20 +194,24 @@ BEGIN CONTROL "",IDC_INFO_BOX_TEXT,"RichEdit20A",ES_MULTILINE | ES_READONLY | ES_NUMBER | WS_BORDER | WS_VSCROLL | WS_TABSTOP,5,6,361,188 END -IDD_KEYFILE_GENERATOR DIALOGEX 0, 0, 308, 270 +IDD_KEYFILE_GENERATOR DIALOGEX 0, 0, 308, 303 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 BEGIN DEFPUSHBUTTON "Close",IDCLOSE,237,10,59,14 COMBOBOX IDC_PRF_ID,79,49,91,90,CBS_DROPDOWNLIST | WS_TABSTOP - PUSHBUTTON "Generate and Save Keyfile...",IDC_GENERATE_AND_SAVE_KEYFILE,89,248,131,14 + PUSHBUTTON "Generate and Save Keyfile...",IDC_GENERATE_AND_SAVE_KEYFILE,92,281,131,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,213,33 CONTROL "",IDC_STATIC,"Static",SS_ETCHEDHORZ,1,40,307,1,WS_EX_STATICEDGE RTEXT "Mixing PRF:",IDT_PRF,6,51,67,10,SS_CENTERIMAGE 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 + LTEXT "Number of keyfiles:",IDT_NUMBER_KEYFILES,9,247,75,8 + EDITTEXT IDC_NUMBER_KEYFILES,92,244,51,14,ES_RIGHT | ES_AUTOHSCROLL | ES_NUMBER + LTEXT "Keyfiles base name:",IDT_KEYFILES_BASE_NAME,9,266,75,8 + EDITTEXT IDC_KEYFILES_BASE_NAME,92,263,131,14,ES_AUTOHSCROLL END IDD_MULTI_CHOICE_DLG DIALOGEX 0, 0, 167, 322 @@ -373,7 +377,7 @@ BEGIN LEFTMARGIN, 7 RIGHTMARGIN, 299 TOPMARGIN, 7 - BOTTOMMARGIN, 266 + BOTTOMMARGIN, 299 END IDD_MULTI_CHOICE_DLG, DIALOG @@ -450,12 +454,12 @@ IDR_BOOT_LOADER_AES BIN "..\\Boot\\Windows\\Release_AES\ IDR_BOOT_LOADER_SERPENT BIN "..\\Boot\\Windows\\Release_Serpent\\BootLoader.com.gz" IDR_BOOT_LOADER_TWOFISH BIN "..\\Boot\\Windows\\Release_Twofish\\BootLoader.com.gz" -IDR_BOOT_SECTOR_SHA2 BIN "..\\Boot\\Windows\\Release_SHA2\\BootSector.bin" -IDR_BOOT_SECTOR_AES_SHA2 BIN "..\\Boot\\Windows\\Release_AES_SHA2\\BootSector.bin" +IDR_BOOT_SECTOR_SHA2 BIN "..\\Boot\\Windows\\Release_SHA2\\BootSector.bin" +IDR_BOOT_SECTOR_AES_SHA2 BIN "..\\Boot\\Windows\\Release_AES_SHA2\\BootSector.bin" IDR_BOOT_SECTOR_SERPENT_SHA2 BIN "..\\Boot\\Windows\\Release_Serpent_SHA2\\BootSector.bin" IDR_BOOT_SECTOR_TWOFISH_SHA2 BIN "..\\Boot\\Windows\\Release_Twofish_SHA2\\BootSector.bin" -IDR_BOOT_LOADER_SHA2 BIN "..\\Boot\\Windows\\Release_SHA2\\BootLoader.com.gz" -IDR_BOOT_LOADER_AES_SHA2 BIN "..\\Boot\\Windows\\Release_AES_SHA2\\BootLoader.com.gz" +IDR_BOOT_LOADER_SHA2 BIN "..\\Boot\\Windows\\Release_SHA2\\BootLoader.com.gz" +IDR_BOOT_LOADER_AES_SHA2 BIN "..\\Boot\\Windows\\Release_AES_SHA2\\BootLoader.com.gz" IDR_BOOT_LOADER_SERPENT_SHA2 BIN "..\\Boot\\Windows\\Release_Serpent_SHA2\\BootLoader.com.gz" IDR_BOOT_LOADER_TWOFISH_SHA2 BIN "..\\Boot\\Windows\\Release_Twofish_SHA2\\BootLoader.com.gz" @@ -469,14 +473,14 @@ IDR_RESCUE_LOADER_AES BIN "..\\Boot\\Windows\\Rescue_AES\\ IDR_RESCUE_LOADER_SERPENT BIN "..\\Boot\\Windows\\Rescue_Serpent\\BootLoader.com.gz" IDR_RESCUE_LOADER_TWOFISH BIN "..\\Boot\\Windows\\Rescue_Twofish\\BootLoader.com.gz" -IDR_RESCUE_BOOT_SECTOR_SHA2 BIN "..\\Boot\\Windows\\Rescue_SHA2\\BootSector.bin" +IDR_RESCUE_BOOT_SECTOR_SHA2 BIN "..\\Boot\\Windows\\Rescue_SHA2\\BootSector.bin" IDR_RESCUE_BOOT_SECTOR_AES_SHA2 BIN "..\\Boot\\Windows\\Rescue_AES_SHA2\\BootSector.bin" IDR_RESCUE_BOOT_SECTOR_SERPENT_SHA2 BIN "..\\Boot\\Windows\\Rescue_Serpent_SHA2\\BootSector.bin" IDR_RESCUE_BOOT_SECTOR_TWOFISH_SHA2 BIN "..\\Boot\\Windows\\Rescue_Twofish_SHA2\\BootSector.bin" -IDR_RESCUE_LOADER_SHA2 BIN "..\\Boot\\Windows\\Rescue_SHA2\\BootLoader.com.gz" -IDR_RESCUE_LOADER_AES_SHA2 BIN "..\\Boot\\Windows\\Rescue_AES_SHA2\\BootLoader.com.gz" -IDR_RESCUE_LOADER_SERPENT_SHA2 BIN "..\\Boot\\Windows\\Rescue_Serpent_SHA2\\BootLoader.com.gz" -IDR_RESCUE_LOADER_TWOFISH_SHA2 BIN "..\\Boot\\Windows\\Rescue_Twofish_SHA2\\BootLoader.com.gz" +IDR_RESCUE_LOADER_SHA2 BIN "..\\Boot\\Windows\\Rescue_SHA2\\BootLoader.com.gz" +IDR_RESCUE_LOADER_AES_SHA2 BIN "..\\Boot\\Windows\\Rescue_AES_SHA2\\BootLoader.com.gz" +IDR_RESCUE_LOADER_SERPENT_SHA2 BIN "..\\Boot\\Windows\\Rescue_Serpent_SHA2\\BootLoader.com.gz" +IDR_RESCUE_LOADER_TWOFISH_SHA2 BIN "..\\Boot\\Windows\\Rescue_Twofish_SHA2\\BootLoader.com.gz" ///////////////////////////////////////////////////////////////////////////// // diff --git a/src/Common/Dlgcode.c b/src/Common/Dlgcode.c index e6686c2c..96938962 100644 --- a/src/Common/Dlgcode.c +++ b/src/Common/Dlgcode.c @@ -350,6 +350,57 @@ std::string ToUpperCase (const std::string &str) return u; } +size_t TrimWhiteSpace(char *str) +{ + char *end, *ptr = str; + size_t out_size; + + if(!str || *str == 0) + return 0; + + // Trim leading space + while(isspace(*ptr)) ptr++; + + if(*ptr == 0) // All spaces? + { + *str = 0; + return 0; + } + + // Trim trailing space + end = str + strlen(str) - 1; + while(end > ptr && isspace(*end)) end--; + end++; + + // Set output size to trimmed string length + out_size = (end - ptr); + + // Copy trimmed string and add null terminator + memmove(str, ptr, out_size); + str[out_size] = 0; + + return out_size; +} + +// check the validity of a file name +BOOL IsValidFileName(const char* str) +{ + static char invalidChars[9] = {'<', '>', ':', '"', '/', '\\', '|', '?', '*'}; + char c; + int i; + BOOL bNotDotOnly = FALSE; + while ((c = *str)) + { + if (c != '.') + bNotDotOnly = TRUE; + for (i= 0; i < sizeof(invalidChars); i++) + if (c == invalidChars[i]) + return FALSE; + str++; + } + + return bNotDotOnly; +} BOOL IsVolumeDeviceHosted (const char *lpszDiskFile) { @@ -4945,6 +4996,10 @@ BOOL CALLBACK KeyfileGeneratorDlgProc (HWND hwndDlg, UINT msg, WPARAM wParam, LP #endif SetTimer (hwndDlg, 0xfd, RANDPOOL_DISPLAY_REFRESH_INTERVAL, NULL); SendMessage (GetDlgItem (hwndDlg, IDC_POOL_CONTENTS), WM_SETFONT, (WPARAM) hFixedDigitFont, (LPARAM) TRUE); + SendMessage (GetDlgItem (hwndDlg, IDC_NUMBER_KEYFILES), EM_SETLIMITTEXT, (WPARAM) (TC_MAX_PATH - 1), 0); + SetWindowText(GetDlgItem (hwndDlg, IDC_NUMBER_KEYFILES), "1"); + // set the maximum length of the keyfile base name to (TC_MAX_PATH - 1) + SendMessage (GetDlgItem (hwndDlg, IDC_KEYFILES_BASE_NAME), EM_SETLIMITTEXT, (WPARAM) (TC_MAX_PATH - 1), 0); return 1; } @@ -5011,40 +5066,133 @@ BOOL CALLBACK KeyfileGeneratorDlgProc (HWND hwndDlg, UINT msg, WPARAM wParam, LP if (lw == IDC_GENERATE_AND_SAVE_KEYFILE) { - char szFileName [TC_MAX_PATH]; + char szNumberKeyFiles[TC_MAX_PATH] = {0}; + char szFileBaseName[TC_MAX_PATH]; + char szDirName[TC_MAX_PATH]; + char szFileName [3*TC_MAX_PATH]; unsigned char keyfile [MAX_PASSWORD]; - int fhKeyfile = -1; + int fhKeyfile = -1, status; + long keyfilesCount = 0, i; + char* fileExtensionPtr = 0; + char szSuffix[32]; + BOOL bBaseNameValid = FALSE; - /* Select filename */ - if (!BrowseFiles (hwndDlg, "OPEN_TITLE", szFileName, bHistory, TRUE, NULL)) + if (!GetWindowText(GetDlgItem (hwndDlg, IDC_NUMBER_KEYFILES), szNumberKeyFiles, TC_MAX_PATH)) + szNumberKeyFiles[0] = 0; + + keyfilesCount = strtoul(szNumberKeyFiles, NULL, 0); + if (keyfilesCount <= 0 || keyfilesCount == LONG_MAX) + { + Warning("KEYFILE_INCORRECT_NUMBER"); + SendMessage(hwndDlg, WM_NEXTDLGCTL, (WPARAM) GetDlgItem (hwndDlg, IDC_NUMBER_KEYFILES), TRUE); + return 1; + } + + if (!GetWindowText(GetDlgItem (hwndDlg, IDC_KEYFILES_BASE_NAME), szFileBaseName, TC_MAX_PATH)) + szFileBaseName[0] = 0; + + // Trim trailing space + if (TrimWhiteSpace(szFileBaseName) == 0) + { + Warning("KEYFILE_EMPTY_BASE_NAME"); + SendMessage(hwndDlg, WM_NEXTDLGCTL, (WPARAM) GetDlgItem (hwndDlg, IDC_KEYFILES_BASE_NAME), TRUE); return 1; + } - /* Conceive the file */ - if ((fhKeyfile = _open(szFileName, _O_CREAT|_O_TRUNC|_O_WRONLY|_O_BINARY, _S_IREAD|_S_IWRITE)) == -1) + if (!IsValidFileName(szFileBaseName)) { - handleWin32Error (hwndDlg); + Warning("KEYFILE_INVALID_BASE_NAME"); + SendMessage(hwndDlg, WM_NEXTDLGCTL, (WPARAM) GetDlgItem (hwndDlg, IDC_KEYFILES_BASE_NAME), TRUE); return 1; } - /* Generate the keyfile */ + fileExtensionPtr = strrchr(szFileBaseName, '.'); + + /* Select directory */ + if (!BrowseDirectories (hwndDlg, "SELECT_KEYFILE_GENERATION_DIRECTORY", szDirName)) + return 1; + + if (szDirName[strlen(szDirName) - 1] != '\\' && szDirName[strlen(szDirName) - 1] != '/') + StringCbCat(szDirName, sizeof(szDirName), "\\"); + WaitCursor(); - if (!RandgetBytes (keyfile, sizeof(keyfile), TRUE)) + + for (i= 0; i < keyfilesCount; i++) { + StringCbCopy(szFileName, sizeof(szFileName), szDirName); + + if (i > 0) + { + StringCbPrintfA(szSuffix, sizeof(szSuffix), "_%d", i); + // Append the counter to the name + if (fileExtensionPtr) + { + StringCbCatN(szFileName, sizeof(szFileName), szFileBaseName, (size_t) (fileExtensionPtr - szFileBaseName)); + StringCbCat(szFileName, sizeof(szFileName), szSuffix); + StringCbCat(szFileName, sizeof(szFileName), fileExtensionPtr); + } + else + { + StringCbCat(szFileName, sizeof(szFileName), szFileBaseName); + StringCbCat(szFileName, sizeof(szFileName), szSuffix); + } + } + else + StringCbCat(szFileName, sizeof(szFileName), szFileBaseName); + + // check if the file exists + if ((fhKeyfile = _open(szFileName, _O_RDONLY|_O_BINARY, _S_IREAD|_S_IWRITE)) != -1) + { + WCHAR s[4*TC_MAX_PATH] = {0}; + WCHAR wszFileName[3*TC_MAX_PATH] = {0}; + + _close (fhKeyfile); + + MultiByteToWideChar(CP_ACP, 0, szFileName, -1, wszFileName, sizeof(wszFileName) / sizeof(WCHAR)); + + StringCbPrintfW (s, sizeof(s), GetString ("KEYFILE_ALREADY_EXISTS"), wszFileName); + status = AskWarnNoYesString (s); + if (status == IDNO) + { + NormalCursor(); + return 1; + } + } + + /* Conceive the file */ + if ((fhKeyfile = _open(szFileName, _O_CREAT|_O_TRUNC|_O_WRONLY|_O_BINARY, _S_IREAD|_S_IWRITE)) == -1) + { + NormalCursor(); + handleWin32Error (hwndDlg); + return 1; + } + + /* Generate the keyfile */ + if (!RandgetBytes (keyfile, sizeof(keyfile), TRUE)) + { + _close (fhKeyfile); + DeleteFile (szFileName); + NormalCursor(); + return 1; + } + + /* Write the keyfile */ + status = _write (fhKeyfile, keyfile, sizeof(keyfile)); + burn (keyfile, sizeof(keyfile)); _close (fhKeyfile); - DeleteFile (szFileName); - NormalCursor(); - return 1; + + if (status == -1) + { + NormalCursor(); + handleWin32Error (hwndDlg); + return 1; + } } + NormalCursor(); - /* Write the keyfile */ - if (_write (fhKeyfile, keyfile, sizeof(keyfile)) == -1) - handleWin32Error (hwndDlg); - else - Info("KEYFILE_CREATED"); + Info("KEYFILE_CREATED"); - burn (keyfile, sizeof(keyfile)); - _close (fhKeyfile); return 1; } return 0; diff --git a/src/Common/Language.xml b/src/Common/Language.xml index fb18bf45..1a98b79c 100644 --- a/src/Common/Language.xml +++ b/src/Common/Language.xml @@ -331,6 +331,8 @@ 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. WARNING: If you lose a keyfile or if any bit of its first 1024 kilobytes changes, it will be impossible to mount volumes that use the keyfile! bits + Number of keyfiles: + Keyfiles base name: Translated by: Plaintext size: bits @@ -600,6 +602,7 @@ Select destination directory Select Keyfile Select a keyfile search path. WARNING: Note that only the path will be remembered, not the filenames! + Select a directory where to store the keyfiles. Designed by Ross Anderson, Eli Biham, and Lars Knudsen. Published in 1998. 256-bit key, 128-bit block. Mode of operation is XTS. Serpent was one of the AES finalists. Please specify the size of the container you want to create.\n\nIf you create a dynamic (sparse-file) container, this parameter will specify its maximum possible size.\n\nNote that the minimum possible size of a FAT volume is 292 KB. The minimum possible size of an NTFS volume is 3792 KB. Please specify the size of the outer volume to be created (you will first create the outer volume and then a hidden volume within it). The minimum possible size of a volume within which a hidden volume is intended to be created is 340 KB. @@ -863,7 +866,11 @@ Enter password for the normal/outer volume Enter password for the hidden volume Enter password for the header stored in backup file - Keyfile has been successfully created. + Keyfiles have been successfully created. + The number of keyfiles you supplied is invalid. + Please enter a name for the keyfile(s) to be generated + The base name of the keyfile(s) is invalid + The keyfile '%s' already exists.\nDo you want to overwrite it? The generation process will be stopped if you answer No. WARNING: The header of this volume is damaged! VeraCrypt automatically used the backup of the volume header embedded in the volume.\n\nYou should repair the volume header by selecting 'Tools' > 'Restore Volume Header'. Volume header backup has been successfully created.\n\nIMPORTANT: Restoring the volume header using this backup will also restore the current volume password. Moreover, if keyfile(s) are/is necessary to mount the volume, the same keyfile(s) will be necessary to mount the volume again when the volume header is restored.\n\nWARNING: This volume header backup may be used to restore the header ONLY of this particular volume. If you use this header backup to restore a header of a different volume, you will be able to mount the volume, but you will NOT be able to decrypt any data stored in the volume (because you will change its master key). The volume header has been successfully restored.\n\nIMPORTANT: Please note that an old password may have been restored as well. Moreover, if keyfile(s) were/was necessary to mount the volume when the backup was created, the same keyfile(s) are now necessary to mount the volume again. @@ -1217,7 +1224,7 @@ Do you want VeraCrypt to attempt to disable write protection of the partition/drive? WARNING: This setting may degrade performance.\n\nAre you sure you want to use this setting? Warning: VeraCrypt volume auto-dismounted - Before you physically remove or turn off a device containing a mounted volume, you should always dismount the volume in VeraCrypt first.\n\nUnexpected spontaneous dismount is usually caused by an intermittently failing cable, drive (enclosure), etc. + Before you physically remove or turn off a device containing a mounted volume, you should always dismount the volume in VeraCrypt first.\n\nUnexpected spontaneous dismount is usually caused by an intermittently failing cable, drive (enclosure), etc. Test Keyfile Backspace diff --git a/src/Common/Resource.h b/src/Common/Resource.h index 9d04e444..2b75ea88 100644 --- a/src/Common/Resource.h +++ b/src/Common/Resource.h @@ -43,18 +43,18 @@ #define IDD_NEW_TOKEN_KEYFILE 539 #define IDD_RANDOM_POOL_ENRICHMENT 540 #define IDI_TRUECRYPT_MOUNTED_ICON 541 -#define IDR_BOOT_SECTOR_SHA2 542 -#define IDR_BOOT_SECTOR_AES_SHA2 543 -#define IDR_BOOT_SECTOR_SERPENT_SHA2 544 -#define IDR_BOOT_SECTOR_TWOFISH_SHA2 545 +#define IDR_BOOT_SECTOR_SHA2 542 +#define IDR_BOOT_SECTOR_AES_SHA2 543 +#define IDR_BOOT_SECTOR_SERPENT_SHA2 544 +#define IDR_BOOT_SECTOR_TWOFISH_SHA2 545 #define IDR_BOOT_LOADER_SHA2 546 #define IDR_BOOT_LOADER_AES_SHA2 547 #define IDR_BOOT_LOADER_SERPENT_SHA2 548 -#define IDR_BOOT_LOADER_TWOFISH_SHA2 549 -#define IDR_RESCUE_BOOT_SECTOR_SHA2 550 -#define IDR_RESCUE_BOOT_SECTOR_AES_SHA2 551 -#define IDR_RESCUE_BOOT_SECTOR_SERPENT_SHA2 552 -#define IDR_RESCUE_BOOT_SECTOR_TWOFISH_SHA2 553 +#define IDR_BOOT_LOADER_TWOFISH_SHA2 549 +#define IDR_RESCUE_BOOT_SECTOR_SHA2 550 +#define IDR_RESCUE_BOOT_SECTOR_AES_SHA2 551 +#define IDR_RESCUE_BOOT_SECTOR_SERPENT_SHA2 552 +#define IDR_RESCUE_BOOT_SECTOR_TWOFISH_SHA2 553 #define IDR_RESCUE_LOADER_SHA2 554 #define IDR_RESCUE_LOADER_AES_SHA2 555 #define IDR_RESCUE_LOADER_SERPENT_SHA2 556 @@ -176,6 +176,10 @@ #define IDC_CONTINUE 5114 #define IDT_ABOUT_RELEASE 5115 #define IDT_STATIC_MODELESS_WAIT_DLG_INFO 5116 +#define IDT_NUMBER_KEYFILES 5117 +#define IDC_NUMBER_KEYFILES 5118 +#define IDT_KEYFILES_BASE_NAME 5119 +#define IDC_KEYFILES_BASE_NAME 5120 // Next default values for new objects // @@ -184,7 +188,7 @@ #define _APS_NO_MFC 1 #define _APS_NEXT_RESOURCE_VALUE 542 #define _APS_NEXT_COMMAND_VALUE 40001 -#define _APS_NEXT_CONTROL_VALUE 5117 +#define _APS_NEXT_CONTROL_VALUE 5121 #define _APS_NEXT_SYMED_VALUE 101 #endif #endif -- cgit v1.2.3